├── .expo-shared ├── README.md └── assets.json ├── .gitignore ├── .prettierignore ├── .solidarity ├── App.js ├── README.md ├── app.json ├── app ├── app.tsx ├── components │ ├── auto-image │ │ ├── auto-image.story.tsx │ │ └── auto-image.tsx │ ├── back-button │ │ ├── back-button.story.tsx │ │ └── back-button.tsx │ ├── bullet-item │ │ └── bullet-item.tsx │ ├── button │ │ ├── button.presets.ts │ │ ├── button.props.ts │ │ ├── button.story.tsx │ │ └── button.tsx │ ├── checkbox │ │ ├── checkbox.props.ts │ │ ├── checkbox.story.tsx │ │ └── checkbox.tsx │ ├── conduct │ │ ├── conduct.story.tsx │ │ └── conduct.tsx │ ├── contact │ │ ├── contact.story.tsx │ │ └── contact.tsx │ ├── content-link │ │ ├── content-link.story.tsx │ │ └── content-link.tsx │ ├── footer │ │ ├── footer.presets.ts │ │ ├── footer.props.ts │ │ ├── footer.story.tsx │ │ ├── footer.tsx │ │ └── index.ts │ ├── form-row │ │ ├── form-row.presets.ts │ │ ├── form-row.props.tsx │ │ ├── form-row.story.tsx │ │ └── form-row.tsx │ ├── gerding-theater │ │ ├── gerding-theater.story.tsx │ │ ├── gerding-theater.tsx │ │ ├── img.venue.png │ │ ├── img.venue@2x.png │ │ └── img.venue@3x.png │ ├── getting-to-chain-react │ │ ├── animations │ │ │ └── scooter-halloween.json │ │ ├── getting-to-chain-react.story.tsx │ │ ├── getting-to-chain-react.tsx │ │ ├── logo-lyft@1x.png │ │ ├── logo-lyft@2x.png │ │ ├── logo-lyft@3x.png │ │ ├── logo-uber@1x.png │ │ ├── logo-uber@2x.png │ │ └── logo-uber@3x.png │ ├── gradient-background │ │ ├── gradient-background.story.tsx │ │ └── gradient-background.tsx │ ├── header │ │ ├── header.props.ts │ │ ├── header.story.tsx │ │ └── header.tsx │ ├── icon │ │ ├── icon.props.ts │ │ ├── icon.story.tsx │ │ ├── icon.tsx │ │ └── icons │ │ │ ├── arrow-left.png │ │ │ ├── arrow-left@2x.png │ │ │ ├── bullet.png │ │ │ ├── bullet@2x.png │ │ │ ├── index.ts │ │ │ └── ladybug.png │ ├── index.ts │ ├── nearby-attractions │ │ ├── attraction.tsx │ │ ├── attractions-list.tsx │ │ ├── attractions-map-callout.tsx │ │ ├── attractions-map.tsx │ │ ├── images │ │ │ ├── Close.png │ │ │ ├── Close@2x.png │ │ │ ├── Close@3x.png │ │ │ ├── star.filled.png │ │ │ ├── star.filled@2x.png │ │ │ ├── star.filled@3x.png │ │ │ ├── star.unfilled.png │ │ │ ├── star.unfilled@2x.png │ │ │ └── star.unfilled@3x.png │ │ ├── nearby-attractions.story.tsx │ │ ├── nearby-attractions.tsx │ │ ├── rating.tsx │ │ └── render-link.tsx │ ├── presented-by │ │ ├── images │ │ │ ├── bg.team.png │ │ │ ├── bg.team@2x.png │ │ │ ├── bg.team@3x.png │ │ │ ├── logo.infinitered.png │ │ │ ├── logo.infinitered@2x.png │ │ │ └── logo.infinitered@3x.png │ │ ├── presented-by.presets.ts │ │ ├── presented-by.story.tsx │ │ └── presented-by.tsx │ ├── schedule-cell │ │ ├── images │ │ │ ├── afterparty-G2i.png │ │ │ ├── coffee-small.png │ │ │ ├── lunch.png │ │ │ ├── panelist.png │ │ │ ├── registration.png │ │ │ └── sponsor-bumped.png │ │ ├── render-image.tsx │ │ ├── render-time.tsx │ │ ├── schedule-cell.presets.ts │ │ ├── schedule-cell.props.ts │ │ ├── schedule-cell.story.tsx │ │ └── schedule-cell.tsx │ ├── schedule-nav │ │ ├── schedule-nav.story.tsx │ │ └── schedule-nav.tsx │ ├── screen │ │ ├── screen.presets.ts │ │ ├── screen.props.ts │ │ └── screen.tsx │ ├── social-button │ │ ├── social-button.presets.ts │ │ ├── social-button.props.ts │ │ ├── social-button.story.tsx │ │ ├── social-button.tsx │ │ └── social_icon_assets │ │ │ ├── dribbble.png │ │ │ ├── dribbble@2x.png │ │ │ ├── dribbble@3x.png │ │ │ ├── email.icon.png │ │ │ ├── email.icon@2x.png │ │ │ ├── email.icon@3x.png │ │ │ ├── facebook.png │ │ │ ├── facebook@2x.png │ │ │ ├── facebook@3x.png │ │ │ ├── github.png │ │ │ ├── github@2x.png │ │ │ ├── github@3x.png │ │ │ ├── instagram.png │ │ │ ├── instagram@2x.png │ │ │ ├── instagram@3x.png │ │ │ ├── link.png │ │ │ ├── link@2x.png │ │ │ ├── link@3x.png │ │ │ ├── medium.png │ │ │ ├── medium@2x.png │ │ │ ├── medium@3x.png │ │ │ ├── phone.icon.png │ │ │ ├── phone.icon@2x.png │ │ │ ├── phone.icon@3x.png │ │ │ ├── slack.png │ │ │ ├── slack@2x.png │ │ │ ├── slack@3x.png │ │ │ ├── twitter.png │ │ │ ├── twitter@2x.png │ │ │ └── twitter@3x.png │ ├── speaker-bio │ │ └── speaker-bio.tsx │ ├── speaker-image │ │ ├── img.speaker.lg.png │ │ ├── img.speaker.lg@2x.png │ │ ├── img.speaker.lg@3x.png │ │ └── speaker-image.tsx │ ├── sponsors │ │ ├── logos │ │ │ ├── Additional_AWS_AA_AfterParty.png │ │ │ ├── Additional_AWS_AA_AfterParty@2x.png │ │ │ ├── Additional_AWS_AA_AfterParty@3x.png │ │ │ ├── Additional_DevLifts_Streches.png │ │ │ ├── Additional_DevLifts_Streches@2x.png │ │ │ ├── Additional_DevLifts_Streches@3x.png │ │ │ ├── Additional_G2i.png │ │ │ ├── Additional_G2i@2x.png │ │ │ ├── Additional_G2i@3x.png │ │ │ ├── Additional_Playstation_Wifi.png │ │ │ ├── Additional_Playstation_Wifi@2x.png │ │ │ ├── Additional_Playstation_Wifi@3x.png │ │ │ ├── Additional_SquarespaceBadges.png │ │ │ ├── Additional_SquarespaceBadges@2x.png │ │ │ ├── Additional_SquarespaceBadges@3x.png │ │ │ ├── Additional_bumped-alt.png │ │ │ ├── Additional_bumped-alt@2x.png │ │ │ ├── Additional_bumped-alt@3x.png │ │ │ ├── Bronze_Airship.png │ │ │ ├── Bronze_Airship@2x.png │ │ │ ├── Bronze_Airship@3x.png │ │ │ ├── Bronze_BuilderX.png │ │ │ ├── Bronze_BuilderX@2x.png │ │ │ ├── Bronze_BuilderX@3x.png │ │ │ ├── Bronze_Cambia.png │ │ │ ├── Bronze_Cambia@2x.png │ │ │ ├── Bronze_Cambia@3x.png │ │ │ ├── Bronze_Echobind.png │ │ │ ├── Bronze_Echobind@2x.png │ │ │ ├── Bronze_Echobind@3x.png │ │ │ ├── Bronze_Facebook.png │ │ │ ├── Bronze_Facebook@2x.png │ │ │ ├── Bronze_Facebook@3x.png │ │ │ ├── Bronze_G2i.png │ │ │ ├── Bronze_G2i@2x.png │ │ │ ├── Bronze_G2i@3x.png │ │ │ ├── Bronze_Modus.png │ │ │ ├── Bronze_Modus@2x.png │ │ │ ├── Bronze_Modus@3x.png │ │ │ ├── Gold_Callstack.png │ │ │ ├── Gold_Callstack@2x.png │ │ │ ├── Gold_Callstack@3x.png │ │ │ ├── Gold_Coinbase.png │ │ │ ├── Gold_Coinbase@2x.png │ │ │ ├── Gold_Coinbase@3x.png │ │ │ ├── Gold_Sentry.png │ │ │ ├── Gold_Sentry@2x.png │ │ │ ├── Gold_Sentry@3x.png │ │ │ ├── Platinum_AWS.png │ │ │ ├── Platinum_AWS@2x.png │ │ │ ├── Platinum_AWS@3x.png │ │ │ ├── Platinum_Amazon_Alexa.png │ │ │ ├── Platinum_Amazon_Alexa@2x.png │ │ │ ├── Platinum_Amazon_Alexa@3x.png │ │ │ ├── Silver_AmazonWebService.png │ │ │ ├── Silver_AmazonWebService@2x.png │ │ │ ├── Silver_AmazonWebService@3x.png │ │ │ ├── Silver_Bugsnag.png │ │ │ ├── Silver_Bugsnag@2x.png │ │ │ ├── Silver_Bugsnag@3x.png │ │ │ ├── Silver_GoDaddy.png │ │ │ ├── Silver_GoDaddy@2x.png │ │ │ ├── Silver_GoDaddy@3x.png │ │ │ ├── Silver_ServerlessGuru.png │ │ │ ├── Silver_ServerlessGuru@2x.png │ │ │ ├── Silver_ServerlessGuru@3x.png │ │ │ ├── playstation.png │ │ │ ├── playstation@2x.png │ │ │ └── playstation@3x.png │ │ ├── sponsor-logo.presets.ts │ │ ├── sponsor-logo.tsx │ │ ├── sponsors.story.tsx │ │ └── sponsors.tsx │ ├── survey-link │ │ ├── survey-link.story.tsx │ │ └── survey-link.tsx │ ├── switch │ │ ├── switch.props.ts │ │ ├── switch.story.tsx │ │ └── switch.tsx │ ├── tab-icon │ │ ├── icons │ │ │ ├── calendar.active.png │ │ │ ├── calendar.active@2x.png │ │ │ ├── calendar.active@3x.png │ │ │ ├── calendar.inactive.png │ │ │ ├── calendar.inactive@2x.png │ │ │ ├── calendar.inactive@3x.png │ │ │ ├── info.active.png │ │ │ ├── info.active@2x.png │ │ │ ├── info.active@3x.png │ │ │ ├── info.inactive.png │ │ │ ├── info.inactive@2x.png │ │ │ ├── info.inactive@3x.png │ │ │ ├── map.active.png │ │ │ ├── map.active@2x.png │ │ │ ├── map.active@3x.png │ │ │ ├── map.inactive.png │ │ │ ├── map.inactive@2x.png │ │ │ ├── map.inactive@3x.png │ │ │ ├── profile.active.png │ │ │ ├── profile.active@2x.png │ │ │ ├── profile.active@3x.png │ │ │ ├── profile.inactive.png │ │ │ ├── profile.inactive@2x.png │ │ │ └── profile.inactive@3x.png │ │ ├── tab-icon.story.tsx │ │ └── tab-icon.tsx │ ├── talk-title │ │ └── talk-title.tsx │ ├── text-field │ │ ├── text-field.story.tsx │ │ └── text-field.tsx │ ├── text │ │ ├── text.presets.ts │ │ ├── text.props.ts │ │ ├── text.story.tsx │ │ └── text.tsx │ ├── title-bar │ │ ├── icon.back-arrow.png │ │ ├── icon.back-arrow@2x.png │ │ ├── icon.back-arrow@3x.png │ │ ├── title-bar.story.tsx │ │ └── title-bar.tsx │ ├── travel-option │ │ ├── Car.png │ │ ├── Car@2x.png │ │ ├── Car@3x.png │ │ ├── Lightrail.png │ │ ├── Lightrail@2x.png │ │ ├── Lightrail@3x.png │ │ ├── travel-option.presets.ts │ │ ├── travel-option.props.ts │ │ ├── travel-option.story.tsx │ │ └── travel-option.tsx │ ├── wallpaper │ │ ├── bg.png │ │ ├── bg@2x.png │ │ ├── wallpaper.presets.ts │ │ ├── wallpaper.props.ts │ │ ├── wallpaper.story.tsx │ │ └── wallpaper.tsx │ └── wi-fi │ │ ├── wi-fi.story.tsx │ │ └── wi-fi.tsx ├── config │ └── env.js ├── i18n │ ├── en.json │ ├── i18n.ts │ ├── index.ts │ └── translate.ts ├── models │ ├── environment.ts │ ├── event-store │ │ ├── event-store.test.ts │ │ └── event-store.ts │ ├── event │ │ └── event.ts │ ├── extensions │ │ ├── with-environment.ts │ │ └── with-root-store.ts │ ├── index.ts │ ├── root-store │ │ ├── root-store-context.ts │ │ ├── root-store.ts │ │ └── setup-root-store.ts │ ├── setting │ │ ├── setting.test.ts │ │ └── setting.ts │ └── speaker │ │ ├── speaker.test.ts │ │ └── speaker.ts ├── navigators │ ├── app-navigator.tsx │ ├── index.ts │ └── navigation-utilities.tsx ├── screens │ ├── code-of-conduct │ │ └── code-of-conduct-screen.tsx │ ├── error │ │ ├── error-boundary.tsx │ │ └── error-component.tsx │ ├── event-details │ │ ├── event-details-screen.tsx │ │ ├── image-dimension-helpers.ts │ │ ├── images │ │ │ ├── bumped.png │ │ │ ├── img.afterparty-g2i.png │ │ │ ├── img.afterparty-squarespace.png │ │ │ ├── img.break.png │ │ │ ├── img.event.png │ │ │ ├── img.event@2x.png │ │ │ ├── img.event@3x.png │ │ │ ├── img.partylogo.png │ │ │ ├── img.partylogo@2x.png │ │ │ ├── img.partylogo@3x.png │ │ │ ├── sponsor-bumped-thumb.png │ │ │ └── sponsor-bumped.png │ │ ├── render-after-party.tsx │ │ ├── render-announcement.tsx │ │ ├── render-break.tsx │ │ ├── render-default-event.tsx │ │ ├── render-event-type.tsx │ │ ├── render-meal.tsx │ │ ├── render-panel.tsx │ │ ├── render-talk.tsx │ │ └── render-workshop.tsx │ ├── index.ts │ ├── info │ │ └── info-screen.tsx │ ├── schedule │ │ ├── render-event.tsx │ │ ├── schedule-content.tsx │ │ ├── schedule-screen.tsx │ │ └── schedule-workshops.tsx │ ├── venue │ │ ├── animations │ │ │ └── sunset.json │ │ └── venue-screen.tsx │ └── welcome │ │ ├── bg.welcome.png │ │ ├── bg.welcome@2x.png │ │ ├── bg.welcome@3x.png │ │ └── welcome-screen.tsx ├── services │ ├── api │ │ ├── api-config.ts │ │ ├── api-problem.test.ts │ │ ├── api-problem.ts │ │ ├── api.ts │ │ ├── api.types.ts │ │ ├── character-api.ts │ │ └── index.ts │ └── reactotron │ │ ├── index.ts │ │ ├── reactotron-config.ts │ │ ├── reactotron.ts │ │ ├── tron.ts │ │ └── tron.web.ts ├── theme │ ├── color.ts │ ├── fonts │ │ └── index.ts │ ├── index.ts │ ├── palette.ts │ ├── spacing.ts │ ├── timing.ts │ └── typography.ts └── utils │ ├── delay.ts │ ├── ignore-warnings.ts │ ├── info.ts │ ├── keychain.ts │ ├── storage │ ├── index.ts │ ├── storage.test.ts │ └── storage.ts │ └── validate.ts ├── assets ├── data │ └── event-data.json ├── fonts │ └── custom-fonts.md └── images │ ├── adaptive-icon.png │ ├── favicon.png │ ├── icon-default.png │ ├── icon-ios.png │ ├── icon.png │ ├── splash-tablet-landscape.png │ ├── splash-tablet-portrait.png │ └── splash.png ├── babel.config.js ├── bin ├── downloadExpoApp.sh ├── postInstall └── setup ├── e2e ├── README.md ├── config.json ├── firstTest.spec.js ├── init.js └── reload.js ├── eas.json ├── ignite └── templates │ ├── component │ ├── NAME.story.tsx.ejs │ └── NAME.tsx.ejs │ ├── model │ ├── NAME.test.ts.ejs │ └── NAME.ts.ejs │ ├── navigator │ └── NAME-navigator.tsx.ejs │ └── screen │ └── NAME-screen.tsx.ejs ├── package.json ├── react-native.config.js ├── storybook ├── index.ts ├── storybook-registry.ts ├── storybook.tsx ├── toggle-storybook.tsx ├── toggle-storybook.web.tsx └── views │ ├── index.ts │ ├── story-screen.tsx │ ├── story.tsx │ └── use-case.tsx ├── test ├── __snapshots__ │ └── storyshots.test.ts.snap ├── i18n.test.ts ├── mock-async-storage.ts ├── mock-file.ts ├── mock-i18n.ts ├── mock-react-native-image.ts ├── mock-reactotron.ts ├── setup.ts └── storyshots.test.ts ├── tsconfig.json ├── webpack.config.js └── yarn.lock /.expo-shared/README.md: -------------------------------------------------------------------------------- 1 | > Why do I have a folder named ".expo-shared" in my project? 2 | 3 | The ".expo-shared" folder is created when running commands that produce state that is intended to be shared with all developers on the project. For example, "npx expo-optimize". 4 | 5 | > What does the "assets.json" file contain? 6 | 7 | The "assets.json" file describes the assets that have been optimized through "expo-optimize" and do not need to be processed again. 8 | 9 | > Should I commit the ".expo-shared" folder? 10 | 11 | Yes, you should share the ".expo-shared" folder with your collaborators. 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | 24 | # Android/IntelliJ 25 | # 26 | build/ 27 | .idea 28 | .gradle 29 | local.properties 30 | *.iml 31 | 32 | # node.js 33 | # 34 | node_modules/ 35 | npm-debug.log 36 | yarn-error.log 37 | 38 | # BUCK 39 | buck-out/ 40 | \.buckd/ 41 | *.keystore 42 | !debug.keystore 43 | 44 | # fastlane 45 | # 46 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 47 | # screenshots whenever they are needed. 48 | # For more information about the recommended setup visit: 49 | # https://docs.fastlane.tools/best-practices/source-control/ 50 | 51 | */fastlane/report.xml 52 | */fastlane/Preview.html 53 | */fastlane/screenshots 54 | 55 | # Bundle artifact 56 | *.jsbundle 57 | 58 | # CocoaPods 59 | /ios/Pods/ 60 | 61 | # Ignite-specific items below 62 | # You can safely replace everything above this comment with whatever is 63 | # in the default .gitignore generated by React-Native CLI 64 | 65 | # VS Code 66 | .vscode 67 | 68 | # Expo 69 | .expo/* 70 | bin/Exponent.app 71 | 72 | npm-debug.* 73 | *.jks 74 | *.p8 75 | *.p12 76 | *.key 77 | *.mobileprovision 78 | *.orig.* 79 | web-build/ 80 | 81 | # Configurations 82 | app/config/env.*.js 83 | !env.js 84 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | ios 3 | android 4 | .vscode 5 | ignite/ignite.json 6 | package.json 7 | -------------------------------------------------------------------------------- /.solidarity: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/solidaritySchema", 3 | "requirements": { 4 | "Node": [{ "rule": "cli", "binary": "node", "semver": ">=8.6.0" }], 5 | "Xcode": [ 6 | { 7 | "rule": "cli", 8 | "binary": "xcodebuild", 9 | "version": "-version", 10 | "semver": ">=9.2.0", 11 | "platform": "darwin" 12 | } 13 | ], 14 | "CocoaPods": [ 15 | { 16 | "rule": "cli", 17 | "binary": "pod", 18 | "version": "--version", 19 | "semver": ">=1.7.0", 20 | "platform": "darwin" 21 | } 22 | ] 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /App.js: -------------------------------------------------------------------------------- 1 | // This is the first file that ReactNative will run when it starts up. 2 | import App from "./app/app.tsx" 3 | import { registerRootComponent } from "expo" 4 | 5 | registerRootComponent(App) 6 | export default App 7 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "ChainReactApp2022", 4 | "slug": "ChainReactApp2022", 5 | "owner": "infinitered", 6 | "version": "2022.0.1", 7 | "orientation": "portrait", 8 | "backgroundColor": "#171539", 9 | "splash": { 10 | "image": "./assets/images/splash.png", 11 | "resizeMode": "contain", 12 | "backgroundColor": "#171539" 13 | }, 14 | "updates": { 15 | "fallbackToCacheTimeout": 0 16 | }, 17 | "assetBundlePatterns": ["**/*"], 18 | "android": { 19 | "icon": "./assets/images/icon.png", 20 | "adaptiveIcon": { 21 | "foregroundImage": "./assets/images/adaptive-icon.png", 22 | "backgroundColor": "#ffffff" 23 | }, 24 | "package": "com.chainreactapp" 25 | }, 26 | "ios": { 27 | "supportsTablet": true, 28 | "icon": "./assets/images/icon-ios.png", 29 | "splash": { 30 | "tabletImage": "./assets/images/splash-tablet-portrait.png" 31 | }, 32 | "bundleIdentifier": "infinitered.stage.ChainReactConf" 33 | }, 34 | "web": { 35 | "favicon": "./assets/images/favicon.png" 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/components/auto-image/auto-image.story.tsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import React from "react" 3 | import { storiesOf } from "@storybook/react-native" 4 | import { StoryScreen, Story, UseCase } from "../../../storybook/views" 5 | import { AutoImage } from "./auto-image" 6 | 7 | declare let module 8 | 9 | const welcomeBG = require("../../screens/welcome/bg.welcome.png") 10 | const morty = { uri: "https://rickandmortyapi.com/api/character/avatar/2.jpeg" } 11 | 12 | storiesOf("AutoImage", module) 13 | .addDecorator((fn) => {fn()}) 14 | .add("Style Presets", () => ( 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | )) 32 | -------------------------------------------------------------------------------- /app/components/auto-image/auto-image.tsx: -------------------------------------------------------------------------------- 1 | import React, { useLayoutEffect, useState } from "react" 2 | import { 3 | Image as RNImage, 4 | ImageProps as DefaultImageProps, 5 | ImageURISource, 6 | Platform, 7 | } from "react-native" 8 | 9 | type ImageProps = DefaultImageProps & { 10 | source: ImageURISource 11 | } 12 | 13 | /** 14 | * An Image wrapper component that autosizes itself to the size of the actual image. 15 | * You can always override by passing a width and height in the style. 16 | * If passing only one of width/height this image component will use the actual 17 | * size of the other dimension. 18 | * 19 | * This component isn't required, but is provided as a convenience so that 20 | * we don't have to remember to explicitly set image sizes on every image instance. 21 | * 22 | * To use as a stand-in replacement import { AutoImage as Image } and remove the 23 | * Image import from react-native. Now all images in that file are handled by this 24 | * component and are web-ready if not explicitly sized in the style property. 25 | */ 26 | export function AutoImage(props: ImageProps) { 27 | const [imageSize, setImageSize] = useState({ width: 0, height: 0 }) 28 | 29 | useLayoutEffect(() => { 30 | if (props.source?.uri) { 31 | RNImage.getSize(props.source.uri as any, (width, height) => { 32 | setImageSize({ width, height }) 33 | }) 34 | } else if (Platform.OS === "web") { 35 | // web requires a different method to get it's size 36 | RNImage.getSize(props.source as any, (width, height) => { 37 | setImageSize({ width, height }) 38 | }) 39 | } else { 40 | const { width, height } = RNImage.resolveAssetSource(props.source) 41 | setImageSize({ width, height }) 42 | } 43 | }, []) 44 | 45 | return 46 | } 47 | -------------------------------------------------------------------------------- /app/components/back-button/back-button.story.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { storiesOf } from "@storybook/react-native" 3 | import { StoryScreen, Story, UseCase } from "../../../storybook/views" 4 | import { BackButton } from "./back-button" 5 | 6 | storiesOf("BackButton", module) 7 | .addDecorator((fn) => {fn()}) 8 | .add("Style Presets", () => ( 9 | 10 | 11 | 12 | 13 | 14 | )) 15 | -------------------------------------------------------------------------------- /app/components/back-button/back-button.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { Image, TextStyle, View, ViewStyle } from "react-native" 3 | import { HIT_SLOP, palette, spacing } from "../../theme" 4 | import { Text } from "../text/text" 5 | 6 | const HEADER_TEXT: TextStyle = { 7 | fontSize: 17, 8 | fontWeight: "600", 9 | lineHeight: 45, 10 | marginLeft: spacing.large, 11 | color: palette.shamrock, 12 | } 13 | 14 | const BACK_ARROW: ViewStyle = { 15 | flexDirection: "row", 16 | paddingLeft: spacing.large, 17 | alignItems: "center", 18 | justifyContent: "center", 19 | } 20 | 21 | export const BackButton = (props: { backTitle: string }) => { 22 | return ( 23 | 24 | 25 | 26 | 27 | ) 28 | } 29 | -------------------------------------------------------------------------------- /app/components/bullet-item/bullet-item.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { View, ViewStyle, ImageStyle, TextStyle } from "react-native" 3 | import { Text } from "../text/text" 4 | import { Icon } from "../icon/icon" 5 | import { spacing, typography } from "../../theme" 6 | 7 | const BULLET_ITEM: ViewStyle = { 8 | flexDirection: "row", 9 | marginTop: spacing[4], 10 | paddingBottom: spacing[4], 11 | borderBottomWidth: 1, 12 | borderBottomColor: "#3A3048", 13 | } 14 | const BULLET_CONTAINER: ViewStyle = { 15 | marginRight: spacing[4] - 1, 16 | marginTop: spacing[2], 17 | } 18 | const BULLET: ImageStyle = { 19 | width: 8, 20 | height: 8, 21 | } 22 | const BULLET_TEXT: TextStyle = { 23 | flex: 1, 24 | fontFamily: typography.primary, 25 | color: "#BAB6C8", 26 | fontSize: 15, 27 | lineHeight: 22, 28 | } 29 | 30 | export interface BulletItemProps { 31 | text: string 32 | } 33 | 34 | export function BulletItem(props: BulletItemProps) { 35 | return ( 36 | 37 | 38 | 39 | 40 | ) 41 | } 42 | -------------------------------------------------------------------------------- /app/components/button/button.presets.ts: -------------------------------------------------------------------------------- 1 | import { TextStyle, ViewStyle } from "react-native" 2 | import { color, palette, spacing } from "../../theme" 3 | 4 | /** 5 | * All text will start off looking like this. 6 | */ 7 | const BASE_VIEW: ViewStyle = { 8 | paddingVertical: spacing.medium, 9 | paddingHorizontal: spacing.medium, 10 | borderRadius: 4, 11 | justifyContent: "center", 12 | alignItems: "center", 13 | } 14 | 15 | const DARK_BASE_VIEW: ViewStyle = { 16 | backgroundColor: color.palette.vintageRock, 17 | paddingVertical: spacing.small, 18 | } 19 | 20 | const BASE_TEXT: TextStyle = { 21 | paddingHorizontal: spacing.large, 22 | } 23 | 24 | /** 25 | * All the variations of text styling within the app. 26 | * 27 | * You want to customize these to whatever you need in your app. 28 | */ 29 | export const viewPresets = { 30 | /** 31 | * A smaller piece of secondary information. 32 | */ 33 | primary: { ...BASE_VIEW, backgroundColor: color.palette.crimson } as ViewStyle, 34 | dark: { ...BASE_VIEW, ...DARK_BASE_VIEW } as ViewStyle, 35 | link: {} as ViewStyle, 36 | } 37 | 38 | export const textPresets = { 39 | primary: { ...BASE_TEXT, fontSize: 9, color: color.palette.white } as TextStyle, 40 | dark: { 41 | color: color.palette.shamrock, 42 | fontSize: 14, 43 | textAlign: "center", 44 | } as TextStyle, 45 | link: { color: palette.shamrock } as TextStyle, 46 | } 47 | 48 | /** 49 | * A list of preset names. 50 | */ 51 | export type ButtonPresetNames = keyof typeof viewPresets 52 | -------------------------------------------------------------------------------- /app/components/button/button.props.ts: -------------------------------------------------------------------------------- 1 | import { StyleProp, TextStyle, TouchableOpacityProps, ViewStyle } from "react-native" 2 | import { ButtonPresetNames } from "./button.presets" 3 | import { TxKeyPath } from "../../i18n" 4 | 5 | export interface ButtonProps extends TouchableOpacityProps { 6 | /** 7 | * Text which is looked up via i18n. 8 | */ 9 | tx?: TxKeyPath 10 | 11 | /** 12 | * The text to display if not using `tx` or nested components. 13 | */ 14 | text?: string 15 | 16 | /** 17 | * An optional style override useful for padding & margin. 18 | */ 19 | style?: StyleProp 20 | 21 | /** 22 | * An optional style override useful for the button text. 23 | */ 24 | textStyle?: StyleProp 25 | 26 | /** 27 | * One of the different types of text presets. 28 | */ 29 | preset?: ButtonPresetNames 30 | 31 | /** 32 | * One of the different types of text presets. 33 | */ 34 | children?: React.ReactNode 35 | } 36 | -------------------------------------------------------------------------------- /app/components/button/button.story.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { ViewStyle, TextStyle, Alert } from "react-native" 3 | import { storiesOf } from "@storybook/react-native" 4 | import { StoryScreen, Story, UseCase } from "../../../storybook/views" 5 | import { Button } from "./button" 6 | 7 | declare let module 8 | 9 | const buttonStyleArray: ViewStyle[] = [{ paddingVertical: 100 }, { borderRadius: 0 }] 10 | 11 | const buttonTextStyleArray: TextStyle[] = [{ fontSize: 20 }, { color: "#a511dc" }] 12 | 13 | storiesOf("Button", module) 14 | .addDecorator((fn) => {fn()}) 15 | .add("Style Presets", () => ( 16 | 17 | 18 | 46 | ) : ( 47 | 48 | )} 49 | 50 | 51 | 52 | {rightIcon ? ( 53 | 56 | ) : ( 57 | 58 | )} 59 | 60 | ) 61 | } 62 | -------------------------------------------------------------------------------- /app/components/icon/icon.props.ts: -------------------------------------------------------------------------------- 1 | import { ImageStyle, StyleProp, ViewStyle } from "react-native" 2 | import { IconTypes } from "./icons" 3 | 4 | export interface IconProps { 5 | /** 6 | * Style overrides for the icon image 7 | */ 8 | style?: StyleProp 9 | 10 | /** 11 | * Style overrides for the icon container 12 | */ 13 | 14 | containerStyle?: StyleProp 15 | 16 | /** 17 | * The name of the icon 18 | */ 19 | 20 | icon?: IconTypes 21 | } 22 | -------------------------------------------------------------------------------- /app/components/icon/icon.story.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { storiesOf } from "@storybook/react-native" 3 | import { StoryScreen, Story, UseCase } from "../../../storybook/views" 4 | import { Icon } from "./icon" 5 | 6 | declare let module 7 | 8 | storiesOf("Icon", module) 9 | .addDecorator((fn) => {fn()}) 10 | .add("Names", () => ( 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | )) 20 | -------------------------------------------------------------------------------- /app/components/icon/icon.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { View, ImageStyle } from "react-native" 3 | import { AutoImage as Image } from "../auto-image/auto-image" 4 | import { IconProps } from "./icon.props" 5 | import { icons } from "./icons" 6 | 7 | const ROOT: ImageStyle = { 8 | resizeMode: "contain", 9 | } 10 | 11 | export function Icon(props: IconProps) { 12 | const { style: styleOverride, icon, containerStyle } = props 13 | 14 | return ( 15 | 16 | 17 | 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /app/components/icon/icons/arrow-left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/icon/icons/arrow-left.png -------------------------------------------------------------------------------- /app/components/icon/icons/arrow-left@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/icon/icons/arrow-left@2x.png -------------------------------------------------------------------------------- /app/components/icon/icons/bullet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/icon/icons/bullet.png -------------------------------------------------------------------------------- /app/components/icon/icons/bullet@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/icon/icons/bullet@2x.png -------------------------------------------------------------------------------- /app/components/icon/icons/index.ts: -------------------------------------------------------------------------------- 1 | export const icons = { 2 | back: require("./arrow-left.png"), 3 | bullet: require("./bullet.png"), 4 | bug: require("./ladybug.png"), 5 | } 6 | 7 | export type IconTypes = keyof typeof icons 8 | -------------------------------------------------------------------------------- /app/components/icon/icons/ladybug.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/icon/icons/ladybug.png -------------------------------------------------------------------------------- /app/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./bullet-item/bullet-item" 2 | export * from "./button/button" 3 | export * from "./checkbox/checkbox" 4 | export * from "./form-row/form-row" 5 | export * from "./header/header" 6 | export * from "./gradient-background/gradient-background" 7 | export * from "./icon/icon" 8 | export * from "./screen/screen" 9 | export * from "./switch/switch" 10 | export * from "./text/text" 11 | export * from "./text-field/text-field" 12 | export * from "./footer/footer" 13 | export * from "./wallpaper/wallpaper" 14 | export * from "./auto-image/auto-image" 15 | export * from "./tab-icon/tab-icon" 16 | export * from "./schedule-cell/schedule-cell" 17 | export * from "./schedule-nav/schedule-nav" 18 | export * from "./speaker-image/speaker-image" 19 | export * from "./talk-title/talk-title" 20 | export * from "./speaker-bio/speaker-bio" 21 | export * from "./back-button/back-button" 22 | export * from "./title-bar/title-bar" 23 | export * from "./gerding-theater/gerding-theater" 24 | export * from "./getting-to-chain-react/getting-to-chain-react" 25 | export * from "./travel-option/travel-option" 26 | export * from "./nearby-attractions/nearby-attractions" 27 | export * from "./content-link/content-link" 28 | export * from "./presented-by/presented-by" 29 | export * from "./wi-fi/wi-fi" 30 | export * from "./conduct/conduct" 31 | export * from "./sponsors/sponsors" 32 | export * from "./survey-link/survey-link" 33 | -------------------------------------------------------------------------------- /app/components/nearby-attractions/attraction.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { TextStyle, View, ViewProps, ViewStyle } from "react-native" 3 | import { Text } from "../text/text" 4 | import { Rating } from "./rating" 5 | import { palette } from "../../theme" 6 | 7 | const ROOT: ViewStyle = { 8 | flex: 1, 9 | paddingVertical: 25, 10 | } 11 | const NAME_WRAPPER: ViewStyle = { 12 | flexDirection: "row", 13 | } 14 | const TITLE_WRAPPER: ViewStyle = { 15 | width: "70%", 16 | } 17 | const TITLE: TextStyle = { 18 | color: palette.white, 19 | } 20 | const ADDRESS: TextStyle = { 21 | color: palette.offWhite, 22 | } 23 | 24 | export interface AttractionProps extends ViewProps { 25 | attraction: any 26 | } 27 | 28 | export const Attraction = (props: AttractionProps) => { 29 | const { attraction } = props 30 | const cleanedAddress = attraction.properties.place_address 31 | .replace(", United States", "") 32 | .replace(", Portland, OR", ",\nPortland, OR") 33 | .replace(", Portland, Oregon", ",\nPortland, OR") 34 | return ( 35 | 36 | 37 | 38 | 43 | 44 | 45 | 46 | 47 | 48 | ) 49 | } 50 | -------------------------------------------------------------------------------- /app/components/nearby-attractions/images/Close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/nearby-attractions/images/Close.png -------------------------------------------------------------------------------- /app/components/nearby-attractions/images/Close@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/nearby-attractions/images/Close@2x.png -------------------------------------------------------------------------------- /app/components/nearby-attractions/images/Close@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/nearby-attractions/images/Close@3x.png -------------------------------------------------------------------------------- /app/components/nearby-attractions/images/star.filled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/nearby-attractions/images/star.filled.png -------------------------------------------------------------------------------- /app/components/nearby-attractions/images/star.filled@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/nearby-attractions/images/star.filled@2x.png -------------------------------------------------------------------------------- /app/components/nearby-attractions/images/star.filled@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/nearby-attractions/images/star.filled@3x.png -------------------------------------------------------------------------------- /app/components/nearby-attractions/images/star.unfilled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/nearby-attractions/images/star.unfilled.png -------------------------------------------------------------------------------- /app/components/nearby-attractions/images/star.unfilled@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/nearby-attractions/images/star.unfilled@2x.png -------------------------------------------------------------------------------- /app/components/nearby-attractions/images/star.unfilled@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/nearby-attractions/images/star.unfilled@3x.png -------------------------------------------------------------------------------- /app/components/nearby-attractions/nearby-attractions.story.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { storiesOf } from "@storybook/react-native" 3 | import { Story, StoryScreen, UseCase } from "../../../storybook/views" 4 | import { NearbyAttractions } from "./nearby-attractions" 5 | 6 | storiesOf("NearbyAttractions", module) 7 | .addDecorator((fn) => {fn()}) 8 | .add("Style Presets", () => ( 9 | 10 | 11 | 12 | 13 | 14 | )) 15 | -------------------------------------------------------------------------------- /app/components/nearby-attractions/nearby-attractions.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { View, ViewStyle } from "react-native" 3 | import { getScreenWidth, palette, spacing } from "../../theme" 4 | import { AttractionsList } from "./attractions-list" 5 | import { AttractionsMap } from "./attractions-map" 6 | 7 | const ROOT: ViewStyle = { 8 | paddingTop: spacing.large, 9 | backgroundColor: palette.portGoreLight, 10 | } 11 | 12 | export const NearbyAttractions = () => { 13 | const fullWidth = { 14 | width: getScreenWidth(), 15 | } 16 | return ( 17 | 18 | 19 | 20 | 21 | ) 22 | } 23 | -------------------------------------------------------------------------------- /app/components/nearby-attractions/rating.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { Image, ImageStyle, View, ViewStyle } from "react-native" 3 | 4 | const filled = require("./images/star.filled.png") 5 | const empty = require("./images/star.unfilled.png") 6 | 7 | const ROOT: ViewStyle = { 8 | marginLeft: "auto", 9 | flexDirection: "row", 10 | width: 17 * 5, 11 | height: 11, 12 | } 13 | const STAR: ImageStyle = { 14 | width: 11, 15 | height: 11, 16 | marginLeft: 6, 17 | } 18 | 19 | type RatingProps = { rating?: number } 20 | 21 | export const Rating = (props: RatingProps) => { 22 | const stars = [1, 2, 3, 4, 5] 23 | const { rating } = props 24 | 25 | return ( 26 | 27 | {stars.map((i) => ( 28 | 29 | ))} 30 | 31 | ) 32 | } 33 | -------------------------------------------------------------------------------- /app/components/nearby-attractions/render-link.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { Linking, TextStyle, TouchableOpacity } from "react-native" 3 | import { Text } from ".." 4 | import { color } from "../../theme" 5 | 6 | const DIRECTIONS: TextStyle = { 7 | fontSize: 11, 8 | lineHeight: 13, 9 | color: color.palette.white, 10 | letterSpacing: 2, 11 | fontWeight: "500", 12 | } 13 | 14 | type RenderLinkProps = { 15 | link: string 16 | } 17 | export const RenderLink = ({ link }: RenderLinkProps) => { 18 | const openLink = () => { 19 | Linking.canOpenURL(link).then((supported) => { 20 | if (!supported) return 21 | Linking.openURL(link) 22 | }) 23 | } 24 | return ( 25 | 26 | 27 | 28 | ) 29 | } 30 | -------------------------------------------------------------------------------- /app/components/presented-by/images/bg.team.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/presented-by/images/bg.team.png -------------------------------------------------------------------------------- /app/components/presented-by/images/bg.team@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/presented-by/images/bg.team@2x.png -------------------------------------------------------------------------------- /app/components/presented-by/images/bg.team@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/presented-by/images/bg.team@3x.png -------------------------------------------------------------------------------- /app/components/presented-by/images/logo.infinitered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/presented-by/images/logo.infinitered.png -------------------------------------------------------------------------------- /app/components/presented-by/images/logo.infinitered@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/presented-by/images/logo.infinitered@2x.png -------------------------------------------------------------------------------- /app/components/presented-by/images/logo.infinitered@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/presented-by/images/logo.infinitered@3x.png -------------------------------------------------------------------------------- /app/components/presented-by/presented-by.presets.ts: -------------------------------------------------------------------------------- 1 | import { ViewStyle } from "react-native" 2 | import { spacing } from "../../theme" 3 | 4 | /** 5 | * All text will start off looking like this. 6 | */ 7 | const BASE_VIEW: ViewStyle = { 8 | flex: 1, 9 | justifyContent: "center", 10 | marginTop: spacing.ginormous + spacing.large, 11 | paddingHorizontal: spacing.large, 12 | } 13 | 14 | /** 15 | * All the variations of text styling within the app. 16 | * 17 | * You want to customize these to whatever you need in your app. 18 | */ 19 | export const presentedByPresets = { 20 | /** 21 | * A smaller piece of secondard information. 22 | */ 23 | default: { ...BASE_VIEW } as ViewStyle, 24 | } 25 | 26 | /** 27 | * A list of preset names. 28 | */ 29 | export type PresentedByPresetNames = keyof typeof presentedByPresets 30 | -------------------------------------------------------------------------------- /app/components/presented-by/presented-by.story.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { storiesOf } from "@storybook/react-native" 3 | import { Story, StoryScreen, UseCase } from "../../../storybook/views" 4 | import { PresentedBy } from "./presented-by" 5 | 6 | storiesOf("PresentedBy", module) 7 | .addDecorator((fn) => {fn()}) 8 | .add("Presets", () => ( 9 | 10 | 11 | 12 | 13 | 14 | )) 15 | -------------------------------------------------------------------------------- /app/components/schedule-cell/images/afterparty-G2i.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/schedule-cell/images/afterparty-G2i.png -------------------------------------------------------------------------------- /app/components/schedule-cell/images/coffee-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/schedule-cell/images/coffee-small.png -------------------------------------------------------------------------------- /app/components/schedule-cell/images/lunch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/schedule-cell/images/lunch.png -------------------------------------------------------------------------------- /app/components/schedule-cell/images/panelist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/schedule-cell/images/panelist.png -------------------------------------------------------------------------------- /app/components/schedule-cell/images/registration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/schedule-cell/images/registration.png -------------------------------------------------------------------------------- /app/components/schedule-cell/images/sponsor-bumped.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/schedule-cell/images/sponsor-bumped.png -------------------------------------------------------------------------------- /app/components/schedule-cell/render-image.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { Image, ImageStyle } from "react-native" 3 | import { Event } from "../../models" 4 | import { ScheduleCellPresets } from "./schedule-cell.presets" 5 | 6 | type RenderImageProps = { 7 | preset: keyof typeof ScheduleCellPresets 8 | event: Event 9 | } 10 | export const RenderImage = (props: RenderImageProps) => { 11 | const { 12 | preset, 13 | event: { sponsor, eventType, speakers }, 14 | event, 15 | } = props 16 | 17 | const style: any = ScheduleCellPresets[preset] || ScheduleCellPresets.default 18 | let image = null 19 | 20 | if (eventType === "panel") { 21 | image = require("./images/panelist.png") 22 | } else if (eventType === "afterparty") { 23 | if (sponsor === "G2i") image = require("./images/afterparty-G2i.png") 24 | if (sponsor === "Bumped") image = require("./images/sponsor-bumped.png") 25 | } else if (eventType === "break") { 26 | image = require("./images/coffee-small.png") 27 | } else if (["talk", "workshop", "welcome", "goodbye"].includes(eventType)) { 28 | image = speakers && speakers[0] && speakers[0].image ? { uri: speakers[0].image } : null 29 | } else if (eventType === "lunch") { 30 | image = require("./images/lunch.png") 31 | } else if (eventType === "breakfast") { 32 | image = require("./images/registration.png") 33 | } else { 34 | if (event.image) image = { uri: event.image } 35 | } 36 | if (image) { 37 | return 38 | } else { 39 | return null 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/components/schedule-cell/render-time.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { TextStyle, View, ViewStyle } from "react-native" 3 | import { Text } from ".." 4 | import { Event } from "../../models" 5 | import { ScheduleCellPresets } from "./schedule-cell.presets" 6 | 7 | type RenderTimeProps = { 8 | preset: keyof typeof ScheduleCellPresets 9 | event: Event 10 | } 11 | 12 | export const RenderTime = (props: RenderTimeProps) => { 13 | const { preset, event } = props 14 | const style: any = ScheduleCellPresets[preset] || ScheduleCellPresets.default 15 | const label = `${event.startTime}` 16 | 17 | return ( 18 | 19 | {event.track && } 20 | 21 | 22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /app/components/schedule-cell/schedule-cell.props.ts: -------------------------------------------------------------------------------- 1 | import { ViewProps } from "react-native" 2 | import { Event } from "../../models" 3 | import { ScheduleCellPresetNames } from "./schedule-cell.presets" 4 | 5 | export interface ScheduleCellProps extends ViewProps { 6 | // Index to determine if cell is even or odd 7 | index: number 8 | event: Event 9 | preset?: ScheduleCellPresetNames 10 | onPress: (event: Event) => void 11 | noTime?: boolean 12 | } 13 | -------------------------------------------------------------------------------- /app/components/schedule-nav/schedule-nav.story.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { storiesOf } from "@storybook/react-native" 3 | import { StoryScreen, Story, UseCase } from "../../../storybook/views" 4 | import { ScheduleNav } from "./schedule-nav" 5 | 6 | storiesOf("ScheduleNav", module) 7 | .addDecorator((fn) => {fn()}) 8 | .add("Style Presets", () => ( 9 | 10 | 11 | {}} /> 12 | 13 | 14 | )) 15 | -------------------------------------------------------------------------------- /app/components/schedule-nav/schedule-nav.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { TextStyle, TouchableOpacity, View, ViewStyle } from "react-native" 3 | import { Text } from "../text/text" 4 | import { palette, spacing } from "../../theme" 5 | import { EVENT_DAYS } from "../../models" 6 | 7 | const NAV_WRAPPER: ViewStyle = { 8 | flexDirection: "row", 9 | } 10 | 11 | const NAV_BUTTON: ViewStyle = { 12 | flex: 1, 13 | justifyContent: "center", 14 | alignItems: "center", 15 | backgroundColor: palette.lightGrey, 16 | paddingTop: spacing.large, 17 | paddingBottom: spacing.medium, 18 | borderRightColor: palette.offWhite, 19 | borderRightWidth: 1, 20 | } 21 | 22 | const NAV_BUTTON_SELECTED: ViewStyle = { 23 | backgroundColor: palette.shamrock, 24 | } 25 | 26 | const NAV_BUTTON_LAST: ViewStyle = { 27 | borderRightWidth: 0, 28 | } 29 | 30 | const NAV_TEXT: TextStyle = { 31 | color: palette.haiti, 32 | } 33 | 34 | type ScheduleNavProps = { 35 | selected: EVENT_DAYS 36 | onSelected: (selected: EVENT_DAYS) => void 37 | } 38 | export const ScheduleNav = ({ selected, onSelected }: ScheduleNavProps) => { 39 | return ( 40 | 41 | onSelected("wednesday")} 44 | > 45 | 46 | 47 | onSelected("thursday")} 50 | > 51 | 52 | 53 | onSelected("friday")} 56 | > 57 | 58 | 59 | 60 | ) 61 | } 62 | -------------------------------------------------------------------------------- /app/components/screen/screen.props.ts: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { StyleProp, ViewStyle } from "react-native" 3 | import { KeyboardOffsets, ScreenPresets } from "./screen.presets" 4 | 5 | export interface ScreenProps { 6 | /** 7 | * Children components. 8 | */ 9 | children?: React.ReactNode 10 | 11 | /** 12 | * An optional style override useful for padding & margin. 13 | */ 14 | style?: StyleProp 15 | 16 | /** 17 | * One of the different types of presets. 18 | */ 19 | preset?: ScreenPresets 20 | 21 | /** 22 | * An optional background color 23 | */ 24 | backgroundColor?: string 25 | 26 | /** 27 | * An optional background image 28 | */ 29 | backgroundImage?: any 30 | 31 | /** 32 | * An optional status bar setting. Defaults to light-content. 33 | */ 34 | statusBar?: "light-content" | "dark-content" 35 | 36 | /** 37 | * Should we not wrap in SafeAreaView? Defaults to false. 38 | */ 39 | unsafe?: boolean 40 | 41 | /** 42 | * By how much should we offset the keyboard? Defaults to none. 43 | */ 44 | keyboardOffset?: KeyboardOffsets 45 | 46 | /** 47 | * Should keyboard persist on screen tap. Defaults to handled. 48 | * Only applies to scroll preset. 49 | */ 50 | keyboardShouldPersistTaps?: "handled" | "always" | "never" 51 | } 52 | -------------------------------------------------------------------------------- /app/components/social-button/social-button.presets.ts: -------------------------------------------------------------------------------- 1 | import { ViewStyle } from "react-native" 2 | 3 | /** 4 | * All text will start off looking like this. 5 | */ 6 | const BASE_VIEW: ViewStyle = { 7 | width: 32, 8 | height: 32, 9 | justifyContent: "center", 10 | alignItems: "center", 11 | } 12 | 13 | /** 14 | * All the variations of text styling within the app. 15 | * 16 | * You want to customize these to whatever you need in your app. 17 | */ 18 | export const viewPresets = { 19 | /** 20 | * A smaller piece of secondard information. 21 | */ 22 | default: { ...BASE_VIEW } as ViewStyle, 23 | } 24 | 25 | export const imageSource = { 26 | websites: require("./social_icon_assets/link.png"), 27 | website: require("./social_icon_assets/link.png"), 28 | twitter: require("./social_icon_assets/twitter.png"), 29 | github: require("./social_icon_assets/github.png"), 30 | medium: require("./social_icon_assets/medium.png"), 31 | dribbble: require("./social_icon_assets/dribbble.png"), 32 | instagram: require("./social_icon_assets/instagram.png"), 33 | facebook: require("./social_icon_assets/facebook.png"), 34 | email: require("./social_icon_assets/email.icon.png"), 35 | phone: require("./social_icon_assets/phone.icon.png"), 36 | slack: require("./social_icon_assets/slack.png"), 37 | } 38 | 39 | export const imageStyle = { 40 | default: {}, 41 | } 42 | 43 | /** 44 | * A list of preset names. 45 | */ 46 | export type SocialButtonPresetNames = keyof typeof imageSource 47 | -------------------------------------------------------------------------------- /app/components/social-button/social-button.props.ts: -------------------------------------------------------------------------------- 1 | import { TouchableOpacityProperties } from "react-native" 2 | import { SocialButtonPresetNames } from "./social-button.presets" 3 | 4 | export interface SocialButtonProps extends TouchableOpacityProperties { 5 | /** 6 | * One of the different types of text presets. 7 | */ 8 | preset?: SocialButtonPresetNames 9 | link: string 10 | } 11 | -------------------------------------------------------------------------------- /app/components/social-button/social-button.story.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { storiesOf } from "@storybook/react-native" 3 | import { Story, StoryScreen, UseCase } from "../../../storybook/views" 4 | import { SocialButton } from "./social-button" 5 | 6 | storiesOf("SocialButton", module) 7 | .addDecorator((fn) => {fn()}) 8 | .add("Presets", () => ( 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | )) 36 | -------------------------------------------------------------------------------- /app/components/social-button/social-button.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { Image, Linking, TouchableHighlight } from "react-native" 3 | import { imageSource, imageStyle, viewPresets } from "./social-button.presets" 4 | import { SocialButtonProps } from "./social-button.props" 5 | import { HIT_SLOP } from "../../theme" 6 | 7 | /** 8 | * Link to social media, using a social media logo. 9 | */ 10 | export function SocialButton(props: SocialButtonProps) { 11 | // grab the props 12 | const { preset = "website", link, style, ...rest } = props 13 | 14 | const image = imageSource[preset] || imageSource["website"] 15 | 16 | return ( 17 | Linking.openURL(link)} 20 | hitSlop={HIT_SLOP} 21 | {...rest} 22 | > 23 | 24 | 25 | ) 26 | } 27 | -------------------------------------------------------------------------------- /app/components/social-button/social_icon_assets/dribbble.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/social-button/social_icon_assets/dribbble.png -------------------------------------------------------------------------------- /app/components/social-button/social_icon_assets/dribbble@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/social-button/social_icon_assets/dribbble@2x.png -------------------------------------------------------------------------------- /app/components/social-button/social_icon_assets/dribbble@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/social-button/social_icon_assets/dribbble@3x.png -------------------------------------------------------------------------------- /app/components/social-button/social_icon_assets/email.icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/social-button/social_icon_assets/email.icon.png -------------------------------------------------------------------------------- /app/components/social-button/social_icon_assets/email.icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/social-button/social_icon_assets/email.icon@2x.png -------------------------------------------------------------------------------- /app/components/social-button/social_icon_assets/email.icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/social-button/social_icon_assets/email.icon@3x.png -------------------------------------------------------------------------------- /app/components/social-button/social_icon_assets/facebook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/social-button/social_icon_assets/facebook.png -------------------------------------------------------------------------------- /app/components/social-button/social_icon_assets/facebook@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/social-button/social_icon_assets/facebook@2x.png -------------------------------------------------------------------------------- /app/components/social-button/social_icon_assets/facebook@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/social-button/social_icon_assets/facebook@3x.png -------------------------------------------------------------------------------- /app/components/social-button/social_icon_assets/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/social-button/social_icon_assets/github.png -------------------------------------------------------------------------------- /app/components/social-button/social_icon_assets/github@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/social-button/social_icon_assets/github@2x.png -------------------------------------------------------------------------------- /app/components/social-button/social_icon_assets/github@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/social-button/social_icon_assets/github@3x.png -------------------------------------------------------------------------------- /app/components/social-button/social_icon_assets/instagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/social-button/social_icon_assets/instagram.png -------------------------------------------------------------------------------- /app/components/social-button/social_icon_assets/instagram@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/social-button/social_icon_assets/instagram@2x.png -------------------------------------------------------------------------------- /app/components/social-button/social_icon_assets/instagram@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/social-button/social_icon_assets/instagram@3x.png -------------------------------------------------------------------------------- /app/components/social-button/social_icon_assets/link.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/social-button/social_icon_assets/link.png -------------------------------------------------------------------------------- /app/components/social-button/social_icon_assets/link@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/social-button/social_icon_assets/link@2x.png -------------------------------------------------------------------------------- /app/components/social-button/social_icon_assets/link@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/social-button/social_icon_assets/link@3x.png -------------------------------------------------------------------------------- /app/components/social-button/social_icon_assets/medium.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/social-button/social_icon_assets/medium.png -------------------------------------------------------------------------------- /app/components/social-button/social_icon_assets/medium@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/social-button/social_icon_assets/medium@2x.png -------------------------------------------------------------------------------- /app/components/social-button/social_icon_assets/medium@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/social-button/social_icon_assets/medium@3x.png -------------------------------------------------------------------------------- /app/components/social-button/social_icon_assets/phone.icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/social-button/social_icon_assets/phone.icon.png -------------------------------------------------------------------------------- /app/components/social-button/social_icon_assets/phone.icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/social-button/social_icon_assets/phone.icon@2x.png -------------------------------------------------------------------------------- /app/components/social-button/social_icon_assets/phone.icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/social-button/social_icon_assets/phone.icon@3x.png -------------------------------------------------------------------------------- /app/components/social-button/social_icon_assets/slack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/social-button/social_icon_assets/slack.png -------------------------------------------------------------------------------- /app/components/social-button/social_icon_assets/slack@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/social-button/social_icon_assets/slack@2x.png -------------------------------------------------------------------------------- /app/components/social-button/social_icon_assets/slack@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/social-button/social_icon_assets/slack@3x.png -------------------------------------------------------------------------------- /app/components/social-button/social_icon_assets/twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/social-button/social_icon_assets/twitter.png -------------------------------------------------------------------------------- /app/components/social-button/social_icon_assets/twitter@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/social-button/social_icon_assets/twitter@2x.png -------------------------------------------------------------------------------- /app/components/social-button/social_icon_assets/twitter@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/social-button/social_icon_assets/twitter@3x.png -------------------------------------------------------------------------------- /app/components/speaker-image/img.speaker.lg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/speaker-image/img.speaker.lg.png -------------------------------------------------------------------------------- /app/components/speaker-image/img.speaker.lg@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/speaker-image/img.speaker.lg@2x.png -------------------------------------------------------------------------------- /app/components/speaker-image/img.speaker.lg@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/speaker-image/img.speaker.lg@3x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Additional_AWS_AA_AfterParty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Additional_AWS_AA_AfterParty.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Additional_AWS_AA_AfterParty@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Additional_AWS_AA_AfterParty@2x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Additional_AWS_AA_AfterParty@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Additional_AWS_AA_AfterParty@3x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Additional_DevLifts_Streches.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Additional_DevLifts_Streches.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Additional_DevLifts_Streches@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Additional_DevLifts_Streches@2x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Additional_DevLifts_Streches@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Additional_DevLifts_Streches@3x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Additional_G2i.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Additional_G2i.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Additional_G2i@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Additional_G2i@2x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Additional_G2i@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Additional_G2i@3x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Additional_Playstation_Wifi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Additional_Playstation_Wifi.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Additional_Playstation_Wifi@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Additional_Playstation_Wifi@2x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Additional_Playstation_Wifi@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Additional_Playstation_Wifi@3x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Additional_SquarespaceBadges.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Additional_SquarespaceBadges.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Additional_SquarespaceBadges@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Additional_SquarespaceBadges@2x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Additional_SquarespaceBadges@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Additional_SquarespaceBadges@3x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Additional_bumped-alt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Additional_bumped-alt.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Additional_bumped-alt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Additional_bumped-alt@2x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Additional_bumped-alt@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Additional_bumped-alt@3x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Bronze_Airship.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Bronze_Airship.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Bronze_Airship@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Bronze_Airship@2x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Bronze_Airship@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Bronze_Airship@3x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Bronze_BuilderX.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Bronze_BuilderX.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Bronze_BuilderX@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Bronze_BuilderX@2x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Bronze_BuilderX@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Bronze_BuilderX@3x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Bronze_Cambia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Bronze_Cambia.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Bronze_Cambia@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Bronze_Cambia@2x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Bronze_Cambia@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Bronze_Cambia@3x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Bronze_Echobind.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Bronze_Echobind.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Bronze_Echobind@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Bronze_Echobind@2x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Bronze_Echobind@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Bronze_Echobind@3x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Bronze_Facebook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Bronze_Facebook.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Bronze_Facebook@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Bronze_Facebook@2x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Bronze_Facebook@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Bronze_Facebook@3x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Bronze_G2i.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Bronze_G2i.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Bronze_G2i@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Bronze_G2i@2x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Bronze_G2i@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Bronze_G2i@3x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Bronze_Modus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Bronze_Modus.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Bronze_Modus@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Bronze_Modus@2x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Bronze_Modus@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Bronze_Modus@3x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Gold_Callstack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Gold_Callstack.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Gold_Callstack@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Gold_Callstack@2x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Gold_Callstack@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Gold_Callstack@3x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Gold_Coinbase.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Gold_Coinbase.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Gold_Coinbase@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Gold_Coinbase@2x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Gold_Coinbase@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Gold_Coinbase@3x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Gold_Sentry.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Gold_Sentry.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Gold_Sentry@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Gold_Sentry@2x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Gold_Sentry@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Gold_Sentry@3x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Platinum_AWS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Platinum_AWS.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Platinum_AWS@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Platinum_AWS@2x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Platinum_AWS@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Platinum_AWS@3x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Platinum_Amazon_Alexa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Platinum_Amazon_Alexa.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Platinum_Amazon_Alexa@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Platinum_Amazon_Alexa@2x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Platinum_Amazon_Alexa@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Platinum_Amazon_Alexa@3x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Silver_AmazonWebService.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Silver_AmazonWebService.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Silver_AmazonWebService@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Silver_AmazonWebService@2x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Silver_AmazonWebService@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Silver_AmazonWebService@3x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Silver_Bugsnag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Silver_Bugsnag.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Silver_Bugsnag@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Silver_Bugsnag@2x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Silver_Bugsnag@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Silver_Bugsnag@3x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Silver_GoDaddy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Silver_GoDaddy.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Silver_GoDaddy@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Silver_GoDaddy@2x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Silver_GoDaddy@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Silver_GoDaddy@3x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Silver_ServerlessGuru.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Silver_ServerlessGuru.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Silver_ServerlessGuru@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Silver_ServerlessGuru@2x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/Silver_ServerlessGuru@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/Silver_ServerlessGuru@3x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/playstation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/playstation.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/playstation@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/playstation@2x.png -------------------------------------------------------------------------------- /app/components/sponsors/logos/playstation@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/sponsors/logos/playstation@3x.png -------------------------------------------------------------------------------- /app/components/sponsors/sponsor-logo.presets.ts: -------------------------------------------------------------------------------- 1 | import { ImageStyle } from "react-native" 2 | import { spacing } from "../../theme" 3 | /** 4 | * All the variations of text styling within the app. 5 | * 6 | * You want to customize these to whatever you need in your app. 7 | */ 8 | const BASE: ImageStyle = { 9 | flex: 1, 10 | resizeMode: "contain", 11 | alignSelf: "center", 12 | margin: spacing.small, 13 | } 14 | 15 | export const sponsorLogoSizePresets = { 16 | platinum: { 17 | ...BASE, 18 | width: "100%", 19 | maxHeight: 135, 20 | marginVertical: spacing.medium, 21 | } as ImageStyle, 22 | gold: { ...BASE, height: 75, maxWidth: "50%" }, 23 | silver: { ...BASE, height: 50, maxWidth: "35%" }, 24 | bronze: { ...BASE, maxHeight: 35, maxWidth: "30%" }, 25 | additional: { ...BASE, height: 60 }, 26 | } 27 | 28 | export const sponsors = { 29 | airship: require("./logos/Bronze_Airship.png"), 30 | alexa: require("./logos/Platinum_Amazon_Alexa.png"), 31 | amazonWeb: require("./logos/Silver_AmazonWebService.png"), 32 | aws: require("./logos/Platinum_AWS.png"), 33 | bugsnag: require("./logos/Silver_Bugsnag.png"), 34 | builderX: require("./logos/Bronze_BuilderX.png"), 35 | bumped: require("./logos/Additional_bumped-alt.png"), 36 | callstack: require("./logos/Gold_Callstack.png"), 37 | cambia: require("./logos/Bronze_Cambia.png"), 38 | coinbase: require("./logos/Gold_Coinbase.png"), 39 | devLifts: require("./logos/Additional_DevLifts_Streches.png"), 40 | echobind: require("./logos/Bronze_Echobind.png"), 41 | facebook: require("./logos/Bronze_Facebook.png"), 42 | g2i: require("./logos/Bronze_G2i.png"), 43 | g2iAdditional: require("./logos/Additional_G2i.png"), 44 | goDaddy: require("./logos/Silver_GoDaddy.png"), 45 | modus: require("./logos/Bronze_Modus.png"), 46 | playstation: require("./logos/Additional_Playstation_Wifi.png"), 47 | sentry: require("./logos/Gold_Sentry.png"), 48 | serverlessGuru: require("./logos/Silver_ServerlessGuru.png"), 49 | squarespace: require("./logos/Additional_SquarespaceBadges.png"), 50 | } 51 | 52 | export type SponsorLogoSizePresetNames = keyof typeof sponsorLogoSizePresets 53 | export type SponsorNames = keyof typeof sponsors 54 | -------------------------------------------------------------------------------- /app/components/sponsors/sponsor-logo.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { Image, ImageStyle, TextStyle, View, ViewStyle } from "react-native" 3 | import { Text } from "../text/text" 4 | import { 5 | SponsorLogoSizePresetNames, 6 | sponsorLogoSizePresets, 7 | SponsorNames, 8 | sponsors, 9 | } from "./sponsor-logo.presets" 10 | import { color } from "../../theme" 11 | 12 | const ROOT: ViewStyle = { 13 | flexDirection: "column", 14 | width: "50%", 15 | alignItems: "center", 16 | } 17 | 18 | const SUBTITLE: TextStyle = { 19 | fontSize: 12, 20 | fontWeight: "600", 21 | letterSpacing: 3.0, 22 | color: color.palette.shamrock, 23 | } 24 | 25 | export type SponsorLogoProps = { 26 | size?: SponsorLogoSizePresetNames 27 | sponsor?: SponsorNames 28 | style?: ImageStyle 29 | subtitle?: string 30 | } 31 | 32 | export const SponsorLogo = (props: SponsorLogoProps) => { 33 | const { size, sponsor, style, subtitle } = props 34 | if (!subtitle) { 35 | return ( 36 | 37 | ) 38 | } else { 39 | return ( 40 | 41 | 45 | {subtitle && } 46 | 47 | ) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/components/sponsors/sponsors.story.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { storiesOf } from "@storybook/react-native" 3 | import { StoryScreen, Story, UseCase } from "../../../storybook/views" 4 | import { color } from "../../theme" 5 | import { Sponsors } from "./sponsors" 6 | 7 | storiesOf("Sponsors", module) 8 | .addDecorator((fn) => {fn()}) 9 | .add("Style Presets", () => ( 10 | 11 | 12 | 13 | 14 | 15 | )) 16 | -------------------------------------------------------------------------------- /app/components/survey-link/survey-link.story.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { storiesOf } from "@storybook/react-native" 3 | import { StoryScreen, Story, UseCase } from "../../../storybook/views" 4 | import { color } from "../../theme" 5 | import { SurveyLink } from "./survey-link" 6 | 7 | storiesOf("SurveyLink", module) 8 | .addDecorator((fn) => {fn()}) 9 | .add("Style Presets", () => ( 10 | 11 | 12 | 13 | 14 | 15 | )) 16 | -------------------------------------------------------------------------------- /app/components/survey-link/survey-link.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | import { Linking } from "react-native" 3 | import { ContentLink } from "../content-link/content-link" 4 | 5 | export function SurveyLink() { 6 | const onPressLink = () => { 7 | Linking.openURL("https://www.surveymonkey.com/r/ChainReact2019") 8 | } 9 | 10 | return ( 11 | 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /app/components/switch/switch.props.ts: -------------------------------------------------------------------------------- 1 | import { StyleProp, ViewStyle } from "react-native" 2 | 3 | export interface SwitchProps { 4 | /** 5 | * On or off. 6 | */ 7 | value?: boolean 8 | /** 9 | * Fires when the on/off switch triggers. 10 | * 11 | * @param newValue The new value we're switching to. 12 | */ 13 | onToggle?: (newValue: boolean) => void 14 | 15 | /** 16 | * A style override to apply to the container. Useful for margins and paddings. 17 | */ 18 | style?: StyleProp 19 | 20 | /** 21 | * Additional track styling when on. 22 | */ 23 | trackOnStyle?: StyleProp 24 | 25 | /** 26 | * Additional track styling when off. 27 | */ 28 | trackOffStyle?: StyleProp 29 | 30 | /** 31 | * Additional thumb styling when on. 32 | */ 33 | thumbOnStyle?: StyleProp 34 | 35 | /** 36 | * Additional thumb styling when off. 37 | */ 38 | thumbOffStyle?: StyleProp 39 | } 40 | -------------------------------------------------------------------------------- /app/components/tab-icon/icons/calendar.active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/tab-icon/icons/calendar.active.png -------------------------------------------------------------------------------- /app/components/tab-icon/icons/calendar.active@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/tab-icon/icons/calendar.active@2x.png -------------------------------------------------------------------------------- /app/components/tab-icon/icons/calendar.active@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/tab-icon/icons/calendar.active@3x.png -------------------------------------------------------------------------------- /app/components/tab-icon/icons/calendar.inactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/tab-icon/icons/calendar.inactive.png -------------------------------------------------------------------------------- /app/components/tab-icon/icons/calendar.inactive@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/tab-icon/icons/calendar.inactive@2x.png -------------------------------------------------------------------------------- /app/components/tab-icon/icons/calendar.inactive@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/tab-icon/icons/calendar.inactive@3x.png -------------------------------------------------------------------------------- /app/components/tab-icon/icons/info.active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/tab-icon/icons/info.active.png -------------------------------------------------------------------------------- /app/components/tab-icon/icons/info.active@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/tab-icon/icons/info.active@2x.png -------------------------------------------------------------------------------- /app/components/tab-icon/icons/info.active@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/tab-icon/icons/info.active@3x.png -------------------------------------------------------------------------------- /app/components/tab-icon/icons/info.inactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/tab-icon/icons/info.inactive.png -------------------------------------------------------------------------------- /app/components/tab-icon/icons/info.inactive@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/tab-icon/icons/info.inactive@2x.png -------------------------------------------------------------------------------- /app/components/tab-icon/icons/info.inactive@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/tab-icon/icons/info.inactive@3x.png -------------------------------------------------------------------------------- /app/components/tab-icon/icons/map.active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/tab-icon/icons/map.active.png -------------------------------------------------------------------------------- /app/components/tab-icon/icons/map.active@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/tab-icon/icons/map.active@2x.png -------------------------------------------------------------------------------- /app/components/tab-icon/icons/map.active@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/tab-icon/icons/map.active@3x.png -------------------------------------------------------------------------------- /app/components/tab-icon/icons/map.inactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/tab-icon/icons/map.inactive.png -------------------------------------------------------------------------------- /app/components/tab-icon/icons/map.inactive@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/tab-icon/icons/map.inactive@2x.png -------------------------------------------------------------------------------- /app/components/tab-icon/icons/map.inactive@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/tab-icon/icons/map.inactive@3x.png -------------------------------------------------------------------------------- /app/components/tab-icon/icons/profile.active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/tab-icon/icons/profile.active.png -------------------------------------------------------------------------------- /app/components/tab-icon/icons/profile.active@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/tab-icon/icons/profile.active@2x.png -------------------------------------------------------------------------------- /app/components/tab-icon/icons/profile.active@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/tab-icon/icons/profile.active@3x.png -------------------------------------------------------------------------------- /app/components/tab-icon/icons/profile.inactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/tab-icon/icons/profile.inactive.png -------------------------------------------------------------------------------- /app/components/tab-icon/icons/profile.inactive@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/tab-icon/icons/profile.inactive@2x.png -------------------------------------------------------------------------------- /app/components/tab-icon/icons/profile.inactive@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/tab-icon/icons/profile.inactive@3x.png -------------------------------------------------------------------------------- /app/components/tab-icon/tab-icon.story.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { storiesOf } from "@storybook/react-native" 3 | import { StoryScreen, Story, UseCase } from "../../../storybook/views" 4 | import { TabIcon } from "./tab-icon" 5 | 6 | storiesOf("TabIcon", module) 7 | .addDecorator((fn) => {fn()}) 8 | .add("Style Presets", () => ( 9 | 10 | 11 | 12 | 13 | 14 | )) 15 | -------------------------------------------------------------------------------- /app/components/tab-icon/tab-icon.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { Image, ImageStyle } from "react-native" 3 | 4 | const ICON: ImageStyle = { 5 | position: "absolute", 6 | alignItems: "center", 7 | justifyContent: "center", 8 | maxHeight: 24, 9 | maxWidth: 24, 10 | } 11 | 12 | const TAB_ICONS = { 13 | schedule: require("./icons/calendar.inactive.png"), 14 | scheduleActive: require("./icons/calendar.active.png"), 15 | venue: require("./icons/map.inactive.png"), 16 | venueActive: require("./icons/map.active.png"), 17 | info: require("./icons/info.inactive.png"), 18 | infoActive: require("./icons/info.active.png"), 19 | profile: require("./icons/profile.inactive.png"), 20 | profileActive: require("./icons/profile.active.png"), 21 | } 22 | 23 | interface Props { 24 | focused?: boolean 25 | routeName: keyof typeof TAB_ICONS 26 | } 27 | 28 | export const TabIcon = ({ routeName, focused }: Props) => { 29 | const tabName = focused ? `${routeName}Active` : routeName 30 | 31 | return 32 | } 33 | -------------------------------------------------------------------------------- /app/components/text/text.props.ts: -------------------------------------------------------------------------------- 1 | import { StyleProp, TextProps as TextProperties, TextStyle } from "react-native" 2 | import i18n from "i18n-js" 3 | import { TextPresets } from "./text.presets" 4 | import { TxKeyPath } from "../../i18n" 5 | 6 | export interface TextProps extends TextProperties { 7 | /** 8 | * Children components. 9 | */ 10 | children?: React.ReactNode 11 | 12 | /** 13 | * Text which is looked up via i18n. 14 | */ 15 | tx?: TxKeyPath 16 | 17 | /** 18 | * Optional options to pass to i18n. Useful for interpolation 19 | * as well as explicitly setting locale or translation fallbacks. 20 | */ 21 | txOptions?: i18n.TranslateOptions 22 | 23 | /** 24 | * The text to display if not using `tx` or nested components. 25 | */ 26 | text?: string 27 | 28 | /** 29 | * An optional style override useful for padding & margin. 30 | */ 31 | style?: StyleProp 32 | 33 | /** 34 | * One of the different types of text presets. 35 | */ 36 | preset?: TextPresets 37 | } 38 | -------------------------------------------------------------------------------- /app/components/text/text.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { Text as ReactNativeText } from "react-native" 3 | import { presets } from "./text.presets" 4 | import { TextProps } from "./text.props" 5 | import { translate } from "../../i18n" 6 | 7 | /** 8 | * For your text displaying needs. 9 | * 10 | * This component is a HOC over the built-in React Native one. 11 | */ 12 | export function Text(props: TextProps) { 13 | // grab the props 14 | const { preset = "default", tx, txOptions, text, children, style: styleOverride, ...rest } = props 15 | 16 | // figure out which content to use 17 | const i18nText = tx && translate(tx, txOptions) 18 | const content = i18nText || text || children 19 | 20 | const style = presets[preset] || presets.default 21 | const styles = [style, styleOverride] 22 | 23 | return ( 24 | 25 | {content} 26 | 27 | ) 28 | } 29 | -------------------------------------------------------------------------------- /app/components/title-bar/icon.back-arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/title-bar/icon.back-arrow.png -------------------------------------------------------------------------------- /app/components/title-bar/icon.back-arrow@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/title-bar/icon.back-arrow@2x.png -------------------------------------------------------------------------------- /app/components/title-bar/icon.back-arrow@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/title-bar/icon.back-arrow@3x.png -------------------------------------------------------------------------------- /app/components/title-bar/title-bar.story.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { storiesOf } from "@storybook/react-native" 3 | import { StoryScreen, Story, UseCase } from "../../../storybook/views" 4 | import { TitleBar } from "./title-bar" 5 | 6 | storiesOf("TitleBar", module) 7 | .addDecorator((fn) => {fn()}) 8 | .add("Style Presets", () => ( 9 | 10 | 11 | 12 | 13 | 14 | )) 15 | -------------------------------------------------------------------------------- /app/components/title-bar/title-bar.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { View, ViewStyle, Image, TextStyle, ImageStyle } from "react-native" 3 | import { Text } from "../text/text" 4 | import { palette, spacing } from "../../theme" 5 | 6 | const ROOT: ViewStyle = { 7 | flexDirection: "row", 8 | backgroundColor: palette.portGore, 9 | padding: spacing.large + spacing.tiny, 10 | } 11 | 12 | const BACK_BUTTON: ImageStyle = { 13 | width: 15, 14 | height: 15, 15 | } 16 | 17 | const TITLE: TextStyle = {} 18 | 19 | export type TitleBarProps = { 20 | title: string 21 | } 22 | 23 | export function TitleBar(props: TitleBarProps) { 24 | return ( 25 | 26 | 27 | 28 | 29 | ) 30 | } 31 | -------------------------------------------------------------------------------- /app/components/travel-option/Car.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/travel-option/Car.png -------------------------------------------------------------------------------- /app/components/travel-option/Car@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/travel-option/Car@2x.png -------------------------------------------------------------------------------- /app/components/travel-option/Car@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/travel-option/Car@3x.png -------------------------------------------------------------------------------- /app/components/travel-option/Lightrail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/travel-option/Lightrail.png -------------------------------------------------------------------------------- /app/components/travel-option/Lightrail@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/travel-option/Lightrail@2x.png -------------------------------------------------------------------------------- /app/components/travel-option/Lightrail@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/travel-option/Lightrail@3x.png -------------------------------------------------------------------------------- /app/components/travel-option/travel-option.presets.ts: -------------------------------------------------------------------------------- 1 | export const presets = { 2 | rideShare: require("./Car.png"), 3 | massTransit: require("./Lightrail.png"), 4 | } 5 | 6 | export type TravelOptionPresets = keyof typeof presets 7 | -------------------------------------------------------------------------------- /app/components/travel-option/travel-option.props.ts: -------------------------------------------------------------------------------- 1 | import { TextProperties } from "react-native" 2 | import { TravelOptionPresets } from "./travel-option.presets" 3 | 4 | export interface TravelOptionProps extends TextProperties { 5 | preset?: TravelOptionPresets 6 | } 7 | -------------------------------------------------------------------------------- /app/components/travel-option/travel-option.story.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { storiesOf } from "@storybook/react-native" 3 | import { StoryScreen, Story, UseCase } from "../../../storybook/views" 4 | import { color } from "../../theme" 5 | import { TravelOption } from "./travel-option" 6 | 7 | storiesOf("TravelOption", module) 8 | .addDecorator((fn) => {fn()}) 9 | .add("Style Presets", () => ( 10 | 11 | 12 | 13 | 14 | 15 | )) 16 | -------------------------------------------------------------------------------- /app/components/travel-option/travel-option.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { Image, TextProps, TextStyle, View, ViewStyle } from "react-native" 3 | import { Text } from "../text/text" 4 | import { spacing } from "../../theme" 5 | 6 | const ROOT: ViewStyle = { 7 | marginTop: spacing.extraLarge, 8 | flexDirection: "row", 9 | } 10 | 11 | const TEXT: TextStyle = { 12 | marginLeft: spacing.large, 13 | paddingVertical: spacing.tiny, 14 | } 15 | 16 | const presets = { 17 | rideShare: require("./Car.png"), 18 | massTransit: require("./Lightrail.png"), 19 | } 20 | 21 | type TravelOptionPresets = keyof typeof presets 22 | interface TravelOptionProps extends TextProps { 23 | preset?: TravelOptionPresets 24 | } 25 | 26 | export const TravelOption = (props: TravelOptionProps) => { 27 | const { preset } = props 28 | return ( 29 | 30 | 31 | 36 | 37 | ) 38 | } 39 | -------------------------------------------------------------------------------- /app/components/wallpaper/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/wallpaper/bg.png -------------------------------------------------------------------------------- /app/components/wallpaper/bg@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/components/wallpaper/bg@2x.png -------------------------------------------------------------------------------- /app/components/wallpaper/wallpaper.presets.ts: -------------------------------------------------------------------------------- 1 | import { ImageStyle } from "react-native" 2 | 3 | /** 4 | * All wallpaper will start off looking like this. 5 | */ 6 | const BASE: ImageStyle = { 7 | position: "absolute", 8 | top: 0, 9 | left: 0, 10 | bottom: 0, 11 | right: 0, 12 | } 13 | 14 | /** 15 | * All the variations of wallpaper styling within the app. 16 | * 17 | * You want to customize these to whatever you need in your app. 18 | */ 19 | export const presets = { 20 | /** 21 | * The default wallpaper styles. 22 | */ 23 | stretch: { 24 | ...BASE, 25 | resizeMode: "stretch", 26 | width: null, // Have to set these to null because android ¯\_(ツ)_/¯ 27 | height: null, 28 | } as ImageStyle, 29 | } 30 | 31 | /** 32 | * A list of preset names. 33 | */ 34 | export type WallpaperPresets = keyof typeof presets 35 | -------------------------------------------------------------------------------- /app/components/wallpaper/wallpaper.props.ts: -------------------------------------------------------------------------------- 1 | import { ImageStyle, StyleProp } from "react-native" 2 | import { WallpaperPresets } from "./wallpaper.presets" 3 | 4 | export interface WallpaperProps { 5 | /** 6 | * An optional style override useful for padding & margin. 7 | */ 8 | style?: StyleProp 9 | 10 | /** 11 | * An optional background image to override the default image. 12 | */ 13 | backgroundImage?: string 14 | 15 | /** 16 | * One of the different types of wallpaper presets. 17 | */ 18 | preset?: WallpaperPresets 19 | } 20 | -------------------------------------------------------------------------------- /app/components/wallpaper/wallpaper.story.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { storiesOf } from "@storybook/react-native" 3 | import { StoryScreen, Story, UseCase } from "../../../storybook/views" 4 | import { Wallpaper } from "./wallpaper" 5 | 6 | declare let module 7 | 8 | storiesOf("Wallpaper", module) 9 | .addDecorator((fn) => {fn()}) 10 | .add("Style Presets", () => ( 11 | 12 | 13 | 14 | 15 | 16 | )) 17 | -------------------------------------------------------------------------------- /app/components/wallpaper/wallpaper.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { AutoImage as Image } from "../auto-image/auto-image" 3 | import { presets } from "./wallpaper.presets" 4 | import { WallpaperProps } from "./wallpaper.props" 5 | 6 | const defaultImage = require("./bg.png") 7 | 8 | /** 9 | * For your text displaying needs. 10 | * 11 | * This component is a HOC over the built-in React Native one. 12 | */ 13 | export function Wallpaper(props: WallpaperProps) { 14 | // grab the props 15 | const { preset = "stretch", style: styleOverride, backgroundImage } = props 16 | 17 | // assemble the style 18 | const presetToUse = presets[preset] || presets.stretch 19 | const styles = [presetToUse, styleOverride] 20 | 21 | // figure out which image to use 22 | const source = backgroundImage || defaultImage 23 | 24 | return 25 | } 26 | -------------------------------------------------------------------------------- /app/components/wi-fi/wi-fi.story.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { storiesOf } from "@storybook/react-native" 3 | import { StoryScreen, Story, UseCase } from "../../../storybook/views" 4 | import { color } from "../../theme" 5 | import { WiFi } from "./wi-fi" 6 | 7 | storiesOf("WiFi", module) 8 | .addDecorator((fn) => {fn()}) 9 | .add("Style Presets", () => ( 10 | 11 | 12 | 13 | 14 | 15 | )) 16 | -------------------------------------------------------------------------------- /app/components/wi-fi/wi-fi.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { Image, ImageStyle, TextStyle, View, ViewStyle } from "react-native" 3 | import { Text } from "../text/text" 4 | import { palette, spacing } from "../../theme" 5 | 6 | const ROOT: ViewStyle = { 7 | marginTop: spacing.large, 8 | paddingHorizontal: spacing.large, 9 | } 10 | const BODY: TextStyle = { 11 | marginTop: spacing.large, 12 | } 13 | const IMAGE: ImageStyle = { 14 | width: "60%", 15 | height: 75, 16 | resizeMode: "contain", 17 | } 18 | const INPUT_WRAPPER: ViewStyle = { 19 | flex: 1, 20 | borderBottomColor: palette.martinique, 21 | borderBottomWidth: 1, 22 | paddingTop: spacing.large, 23 | paddingBottom: 8, 24 | marginTop: 40, 25 | } 26 | const INPUT: TextStyle = { 27 | marginTop: spacing.large, 28 | } 29 | const SPLITZY: ViewStyle = { 30 | flexDirection: "row", 31 | justifyContent: "space-between", 32 | alignItems: "center", 33 | } 34 | 35 | export const WiFi = () => { 36 | return ( 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | ) 53 | } 54 | -------------------------------------------------------------------------------- /app/config/env.js: -------------------------------------------------------------------------------- 1 | module.exports = __DEV__ ? require("./env.dev") : require("./env.prod") 2 | -------------------------------------------------------------------------------- /app/i18n/i18n.ts: -------------------------------------------------------------------------------- 1 | import * as Localization from "expo-localization" 2 | import i18n from "i18n-js" 3 | import en from "./en.json" 4 | // import ja from "./ja.json" 5 | 6 | i18n.fallbacks = true 7 | // i18n.translations = { en, ja } 8 | i18n.translations = { en } 9 | 10 | i18n.locale = Localization.locale || "en" 11 | 12 | /** 13 | * Builds up valid keypaths for translations. 14 | * Update to your default locale of choice if not English. 15 | */ 16 | type DefaultLocale = typeof en 17 | export type TxKeyPath = RecursiveKeyOf 18 | 19 | type RecursiveKeyOf> = { 20 | [TKey in keyof TObj & string]: TObj[TKey] extends Record 21 | ? TKey | `${TKey}.${RecursiveKeyOf}` 22 | : TKey 23 | }[keyof TObj & string] 24 | -------------------------------------------------------------------------------- /app/i18n/index.ts: -------------------------------------------------------------------------------- 1 | import "./i18n" 2 | export * from "./i18n" 3 | export * from "./translate" 4 | -------------------------------------------------------------------------------- /app/i18n/translate.ts: -------------------------------------------------------------------------------- 1 | import i18n from "i18n-js" 2 | import { TxKeyPath } from "./i18n" 3 | 4 | /** 5 | * Translates text. 6 | * 7 | * @param key The i18n key. 8 | */ 9 | export function translate(key: TxKeyPath, options?: i18n.TranslateOptions) { 10 | return key ? i18n.t(key, options) : null 11 | } 12 | -------------------------------------------------------------------------------- /app/models/environment.ts: -------------------------------------------------------------------------------- 1 | import { Api } from "../services/api" 2 | 3 | let ReactotronDev 4 | if (__DEV__) { 5 | const { Reactotron } = require("../services/reactotron") 6 | ReactotronDev = Reactotron 7 | } 8 | 9 | /** 10 | * The environment is a place where services and shared dependencies between 11 | * models live. They are made available to every model via dependency injection. 12 | */ 13 | export class Environment { 14 | constructor() { 15 | // create each service 16 | if (__DEV__) { 17 | // dev-only services 18 | this.reactotron = new ReactotronDev() 19 | } 20 | this.api = new Api() 21 | } 22 | 23 | async setup() { 24 | // allow each service to setup 25 | if (__DEV__) { 26 | await this.reactotron.setup() 27 | } 28 | await this.api.setup() 29 | } 30 | 31 | /** 32 | * Reactotron is only available in dev. 33 | */ 34 | reactotron: typeof ReactotronDev 35 | 36 | /** 37 | * Our api. 38 | */ 39 | api: Api 40 | } 41 | -------------------------------------------------------------------------------- /app/models/event-store/event-store.test.ts: -------------------------------------------------------------------------------- 1 | import { EventStoreModel } from "./event-store" 2 | 3 | test("can be created", () => { 4 | const instance = EventStoreModel.create({}) 5 | 6 | expect(instance).toBeTruthy() 7 | }) 8 | -------------------------------------------------------------------------------- /app/models/event/event.ts: -------------------------------------------------------------------------------- 1 | import { Instance, SnapshotOut, types } from "mobx-state-tree" 2 | import { SpeakerModel } from "../speaker/speaker" 3 | 4 | export type EVENT_DAYS = "wednesday" | "thursday" | "friday" 5 | export const DAYS = ["wednesday", "thursday", "friday"] 6 | 7 | /** 8 | * Info for each conference talk. 9 | */ 10 | export const EventModel = types 11 | .model("Event") 12 | .props({ 13 | id: types.identifier, 14 | startTime: types.string, 15 | endTime: types.string, 16 | duration: types.string, 17 | day: types.enumeration(DAYS), 18 | shortTitle: types.maybeNull(types.string), 19 | title: types.maybeNull(types.string), 20 | description: types.maybeNull(types.string), 21 | image: types.maybeNull(types.string), 22 | speakers: types.array(types.reference(SpeakerModel)), 23 | menuItems: types.maybeNull(types.array(types.string)), 24 | sponsor: types.maybeNull(types.string), 25 | eventType: types.enumeration([ 26 | "talk", 27 | "announcement", 28 | "meal", 29 | "workshop", 30 | "break", 31 | "panel", 32 | "afterparty", 33 | ]), 34 | location: types.maybeNull(types.string), 35 | track: types.maybeNull(types.enumeration(["BEGINNER", "INTERMEDIATE", "ADVANCED"])), 36 | prerequisites: types.maybeNull(types.array(types.string)), 37 | }) 38 | .views((event) => ({ 39 | get screenTitle() { 40 | return event.shortTitle || event.title 41 | }, 42 | })) // eslint-disable-line @typescript-eslint/no-unused-vars 43 | .actions((self) => ({})) // eslint-disable-line @typescript-eslint/no-unused-vars 44 | 45 | type EventType = Instance 46 | export interface Event extends EventType {} 47 | type EventSnapshotType = SnapshotOut 48 | export interface EventSnapshot extends EventSnapshotType {} 49 | export const createEventDefaultModel = () => types.optional(EventModel, {}) 50 | -------------------------------------------------------------------------------- /app/models/extensions/with-environment.ts: -------------------------------------------------------------------------------- 1 | import { getEnv, IStateTreeNode } from "mobx-state-tree" 2 | import { Environment } from "../environment" 3 | 4 | /** 5 | * Adds a environment property to the node for accessing our 6 | * Environment in strongly typed. 7 | */ 8 | export const withEnvironment = (self: IStateTreeNode) => ({ 9 | views: { 10 | /** 11 | * The environment. 12 | */ 13 | get environment() { 14 | return getEnv(self) 15 | }, 16 | }, 17 | }) 18 | -------------------------------------------------------------------------------- /app/models/extensions/with-root-store.ts: -------------------------------------------------------------------------------- 1 | import { getRoot, IStateTreeNode } from "mobx-state-tree" 2 | import { RootStore } from "../root-store/root-store" 3 | 4 | /** 5 | * Adds a rootStore property to the node for a convenient 6 | * and strongly typed way for stores to access other stores. 7 | */ 8 | export const withRootStore = (self: IStateTreeNode) => ({ 9 | views: { 10 | /** 11 | * The root store. 12 | */ 13 | get rootStore(): RootStore { 14 | return getRoot(self) 15 | }, 16 | }, 17 | }) 18 | -------------------------------------------------------------------------------- /app/models/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./extensions/with-environment" 2 | export * from "./extensions/with-root-store" 3 | export * from "./root-store/root-store" 4 | export * from "./root-store/root-store-context" 5 | export * from "./root-store/setup-root-store" 6 | export * from "./event-store/event-store" 7 | export * from "./event/event" 8 | export * from "./setting/setting" 9 | export * from "./speaker/speaker" 10 | -------------------------------------------------------------------------------- /app/models/root-store/root-store-context.ts: -------------------------------------------------------------------------------- 1 | import { createContext, useContext } from "react" 2 | import { RootStore } from "./root-store" 3 | 4 | /** 5 | * Create a context we can use to 6 | * - Provide access to our stores from our root component 7 | * - Consume stores in our screens (or other components, though it's 8 | * preferable to just connect screens) 9 | */ 10 | const RootStoreContext = createContext({} as RootStore) 11 | 12 | /** 13 | * The provider our root component will use to expose the root store 14 | */ 15 | export const RootStoreProvider = RootStoreContext.Provider 16 | 17 | /** 18 | * A hook that screens can use to gain access to our stores, with 19 | * `const { someStore, someOtherStore } = useStores()`, 20 | * or less likely: `const rootStore = useStores()` 21 | */ 22 | export const useStores = (): RootStore => useContext(RootStoreContext) 23 | -------------------------------------------------------------------------------- /app/models/root-store/root-store.ts: -------------------------------------------------------------------------------- 1 | import { Instance, SnapshotOut, types } from "mobx-state-tree" 2 | import { EventStoreModel } from "../event-store/event-store" 3 | 4 | /** 5 | * This is our primary store that holds all other stores. 6 | */ 7 | export const RootStoreModel = types 8 | .model("RootStore") 9 | .props({ 10 | eventStore: types.optional( 11 | types.late(() => EventStoreModel), 12 | {}, 13 | ), 14 | }) 15 | .actions((root) => ({ 16 | async refresh() { 17 | return root.eventStore.refresh() 18 | }, 19 | reset() { 20 | // Need to properly reset everything here 21 | // root.eventStore = EventStoreModel.create({}) 22 | }, 23 | })) 24 | 25 | /** 26 | * The RootStore instance. 27 | */ 28 | export interface RootStore extends Instance {} 29 | 30 | /** 31 | * The data of a RootStore. 32 | */ 33 | export interface RootStoreSnapshot extends SnapshotOut {} 34 | -------------------------------------------------------------------------------- /app/models/setting/setting.test.ts: -------------------------------------------------------------------------------- 1 | import { SettingModel } from "./setting" 2 | 3 | test("can be created", () => { 4 | const instance = SettingModel.create({}) 5 | 6 | expect(instance).toBeTruthy() 7 | }) 8 | -------------------------------------------------------------------------------- /app/models/setting/setting.ts: -------------------------------------------------------------------------------- 1 | import { Instance, SnapshotOut, types } from "mobx-state-tree" 2 | 3 | /** 4 | * Model description here for TypeScript hints. 5 | */ 6 | export const SettingModel = types 7 | .model("Setting") 8 | .props({}) 9 | .views((self) => ({})) // eslint-disable-line @typescript-eslint/no-unused-vars 10 | .actions((self) => ({})) // eslint-disable-line @typescript-eslint/no-unused-vars 11 | 12 | type SettingType = Instance 13 | export interface Setting extends SettingType {} 14 | type SettingSnapshotType = SnapshotOut 15 | export interface SettingSnapshot extends SettingSnapshotType {} 16 | export const createSettingDefaultModel = () => types.optional(SettingModel, {}) 17 | -------------------------------------------------------------------------------- /app/models/speaker/speaker.test.ts: -------------------------------------------------------------------------------- 1 | import { SpeakerModel } from "./speaker" 2 | 3 | test("can be created", () => { 4 | const instance = SpeakerModel.create({ 5 | id: "asdfd", 6 | }) 7 | 8 | expect(instance).toBeTruthy() 9 | }) 10 | -------------------------------------------------------------------------------- /app/models/speaker/speaker.ts: -------------------------------------------------------------------------------- 1 | import { Instance, SnapshotOut, types } from "mobx-state-tree" 2 | 3 | /** 4 | * Info for each speaker. 5 | */ 6 | export const SpeakerModel = types 7 | .model("Speaker") 8 | .props({ 9 | id: types.identifier, 10 | name: types.maybeNull(types.string), 11 | employer: types.maybeNull(types.string), 12 | image: types.maybeNull(types.string), 13 | bio: types.maybeNull(types.string), 14 | facebook: types.maybeNull(types.string), 15 | github: types.maybeNull(types.string), 16 | twitter: types.maybeNull(types.string), 17 | medium: types.maybeNull(types.string), 18 | instagram: types.maybeNull(types.string), 19 | dribbble: types.maybeNull(types.string), 20 | websites: types.maybeNull(types.array(types.string)), 21 | }) 22 | .views((speaker) => ({})) // eslint-disable-line @typescript-eslint/no-unused-vars 23 | .actions((speaker) => ({})) // eslint-disable-line @typescript-eslint/no-unused-vars 24 | 25 | type SpeakerType = Instance 26 | export interface Speaker extends SpeakerType {} 27 | type SpeakerSnapshotType = SnapshotOut 28 | export interface SpeakerSnapshot extends SpeakerSnapshotType {} 29 | export const createSpeakerDefaultModel = () => types.optional(SpeakerModel, {}) 30 | -------------------------------------------------------------------------------- /app/navigators/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./app-navigator" 2 | export * from "./navigation-utilities" 3 | // export other navigators from here 4 | -------------------------------------------------------------------------------- /app/screens/code-of-conduct/code-of-conduct-screen.tsx: -------------------------------------------------------------------------------- 1 | import { useNavigation } from "@react-navigation/core" 2 | import React, { useLayoutEffect } from "react" 3 | import { TextStyle, ViewStyle } from "react-native" 4 | // import { BackButton } from "../../components/back-button" 5 | import { Contact } from "../../components/contact/contact" 6 | import { Screen } from "../../components/screen/screen" 7 | import { Text } from "../../components/text/text" 8 | import { color, spacing } from "../../theme" 9 | import { palette } from "../../theme/palette" 10 | 11 | const ROOT: ViewStyle = { 12 | marginHorizontal: spacing.large, 13 | paddingBottom: spacing.huge, 14 | } 15 | 16 | const TITLE: TextStyle = { 17 | marginTop: spacing.extraLarge, 18 | letterSpacing: 1.68, 19 | } 20 | 21 | const SECTION: TextStyle = { 22 | marginVertical: spacing.medium, 23 | } 24 | 25 | const SECTION_TITLE: TextStyle = { 26 | fontWeight: "500", 27 | letterSpacing: 3.0, 28 | fontSize: 14, 29 | color: color.palette.shamrock, 30 | marginTop: spacing.medium, 31 | } 32 | 33 | const email = "conf@infinite.red" 34 | const twitter = "chainreactconf" 35 | const phoneNumber = "(360) 450-4752" 36 | 37 | export const CodeOfConductScreen = () => { 38 | const navigation = useNavigation() 39 | 40 | useLayoutEffect(() => { 41 | navigation.setOptions({ title: "Code of Conduct" }) 42 | }, [navigation]) 43 | 44 | return ( 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | ) 55 | } 56 | -------------------------------------------------------------------------------- /app/screens/event-details/image-dimension-helpers.ts: -------------------------------------------------------------------------------- 1 | import { spacing } from "../../theme" 2 | const IMAGE_ASPECT_RATIO = 1.5 3 | 4 | export const calculateImageDimensions = (screenWidth) => { 5 | const imageWidth = 0.92 * (screenWidth - 2 * spacing.large) // 92% of the available container, screen width minus twice the screen padding. 6 | const imageHeight = imageWidth / IMAGE_ASPECT_RATIO 7 | return { 8 | height: imageHeight, 9 | width: imageWidth, 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /app/screens/event-details/images/bumped.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/screens/event-details/images/bumped.png -------------------------------------------------------------------------------- /app/screens/event-details/images/img.afterparty-g2i.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/screens/event-details/images/img.afterparty-g2i.png -------------------------------------------------------------------------------- /app/screens/event-details/images/img.afterparty-squarespace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/screens/event-details/images/img.afterparty-squarespace.png -------------------------------------------------------------------------------- /app/screens/event-details/images/img.break.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/screens/event-details/images/img.break.png -------------------------------------------------------------------------------- /app/screens/event-details/images/img.event.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/screens/event-details/images/img.event.png -------------------------------------------------------------------------------- /app/screens/event-details/images/img.event@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/screens/event-details/images/img.event@2x.png -------------------------------------------------------------------------------- /app/screens/event-details/images/img.event@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/screens/event-details/images/img.event@3x.png -------------------------------------------------------------------------------- /app/screens/event-details/images/img.partylogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/screens/event-details/images/img.partylogo.png -------------------------------------------------------------------------------- /app/screens/event-details/images/img.partylogo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/screens/event-details/images/img.partylogo@2x.png -------------------------------------------------------------------------------- /app/screens/event-details/images/img.partylogo@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/screens/event-details/images/img.partylogo@3x.png -------------------------------------------------------------------------------- /app/screens/event-details/images/sponsor-bumped-thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/screens/event-details/images/sponsor-bumped-thumb.png -------------------------------------------------------------------------------- /app/screens/event-details/images/sponsor-bumped.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/screens/event-details/images/sponsor-bumped.png -------------------------------------------------------------------------------- /app/screens/event-details/render-after-party.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { Image, ImageStyle, TextStyle, View, ViewStyle } from "react-native" 3 | import { Text } from "../../components" 4 | import { Event } from "../../models" 5 | import { getScreenWidth, palette, spacing } from "../../theme" 6 | import { calculateImageDimensions } from "./image-dimension-helpers" 7 | 8 | const FULL_SIZE: ViewStyle = { 9 | width: "100%", 10 | height: "100%", 11 | } 12 | 13 | const FULL_WIDTH_IMAGE: ImageStyle = { 14 | resizeMode: "contain", 15 | } 16 | 17 | const TITLE: TextStyle = { 18 | fontSize: 20, 19 | color: palette.white, 20 | marginTop: spacing.large, 21 | } 22 | 23 | const AFTER_PARTY_DESCRIPTION: TextStyle = { marginTop: spacing.small } 24 | 25 | type RenderAfterPartyProps = { event: Event } 26 | export const RenderAfterParty = (props: RenderAfterPartyProps) => { 27 | const { title, description, sponsor, location } = props.event 28 | const imageDimensions = calculateImageDimensions(getScreenWidth()) 29 | 30 | let image = null 31 | switch (sponsor) { 32 | case "Squarespace": 33 | image = require("./images/img.afterparty-squarespace.png") 34 | break 35 | case "Bumped": 36 | image = require("./images/bumped.png") 37 | break 38 | case "G2i": 39 | image = require("./images/img.afterparty-g2i.png") 40 | break 41 | default: 42 | image = require("./images/img.afterparty-g2i.png") 43 | break 44 | } 45 | 46 | return ( 47 | 48 | 49 | 50 | 51 | 52 | 53 | {location && ( 54 | 59 | )} 60 | {location && } 61 | 62 | ) 63 | } 64 | -------------------------------------------------------------------------------- /app/screens/event-details/render-announcement.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { TextStyle, View, ViewStyle } from "react-native" 3 | import { SpeakerBio, SpeakerImage, Text } from "../../components" 4 | import { Event } from "../../models" 5 | import { spacing, textSizes } from "../../theme" 6 | 7 | const FULL_SIZE: ViewStyle = { 8 | width: "100%", 9 | height: "100%", 10 | } 11 | 12 | const PANEL_BIO: ViewStyle = { 13 | flex: 1, 14 | marginTop: spacing.extraLarge + spacing.large, 15 | } 16 | 17 | const TITLE: TextStyle = { 18 | fontSize: textSizes.title, 19 | } 20 | 21 | const DESCRIPTION: TextStyle = { 22 | marginTop: spacing.large + spacing.tiny + spacing.tiny, 23 | } 24 | 25 | type RenderAnnouncementProps = { event: Event } 26 | export const RenderAnnouncement = (props: RenderAnnouncementProps) => { 27 | const { title, description, speakers } = props.event 28 | return ( 29 | 30 | 31 | 32 | {speakers && 33 | speakers.length && 34 | speakers.map((speaker, index) => { 35 | const isLast = index === speakers.length - 1 36 | return ( 37 | 38 | 39 | 40 | 41 | ) 42 | })} 43 | 44 | ) 45 | } 46 | -------------------------------------------------------------------------------- /app/screens/event-details/render-default-event.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { TextStyle, View, ViewStyle } from "react-native" 3 | import { Text } from "../../components" 4 | import { Event } from "../../models" 5 | import { palette, spacing, textSizes } from "../../theme" 6 | 7 | const FULL_SIZE: ViewStyle = { 8 | width: "100%", 9 | height: "100%", 10 | } 11 | 12 | const LABEL: TextStyle = { 13 | marginTop: spacing.extraLarge + spacing.large, 14 | color: palette.shamrock, 15 | marginBottom: spacing.large, 16 | } 17 | 18 | const TITLE: TextStyle = { 19 | fontSize: textSizes.title, 20 | } 21 | 22 | type RenderDefaultEventProps = { event: Event } 23 | 24 | export function RenderDefaultEvent({ event }: RenderDefaultEventProps) { 25 | const { title, description } = event 26 | return ( 27 | 28 | {/* 29 | 30 | */} 31 | 32 | 33 | 34 | 35 | ) 36 | } 37 | -------------------------------------------------------------------------------- /app/screens/event-details/render-event-type.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { Event } from "../../models" 3 | import { RenderBreak } from "./render-break" 4 | import { RenderTalk } from "./render-talk" 5 | import { RenderAnnouncement } from "./render-announcement" 6 | import { RenderWorkshop } from "./render-workshop" 7 | import { RenderMeal } from "./render-meal" 8 | import { RenderAfterParty } from "./render-after-party" 9 | import { RenderPanel } from "./render-panel" 10 | import { RenderDefaultEvent } from "./render-default-event" 11 | 12 | type RenderEventTypeProps = { 13 | event: Event 14 | } 15 | export const RenderEventType = ({ event }: RenderEventTypeProps) => { 16 | switch (event.eventType.toLowerCase()) { 17 | case "talk": 18 | return 19 | case "workshop": 20 | return 21 | case "break": 22 | return 23 | case "meal": 24 | return 25 | case "panel": 26 | return 27 | case "announcement": 28 | return 29 | case "afterparty": 30 | return 31 | default: 32 | return 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/screens/event-details/render-panel.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { Image, ImageStyle, TextStyle, View, ViewStyle } from "react-native" 3 | import { SpeakerBio, SpeakerImage, Text } from "../../components" 4 | import { Event } from "../../models" 5 | import { getScreenWidth, palette, spacing } from "../../theme" 6 | import { calculateImageDimensions } from "./image-dimension-helpers" 7 | 8 | const FULL_SIZE: ViewStyle = { 9 | width: "100%", 10 | height: "100%", 11 | } 12 | 13 | const FULL_WIDTH_IMAGE: ImageStyle = { 14 | resizeMode: "contain", 15 | } 16 | 17 | const TITLE: TextStyle = { 18 | fontSize: 20, 19 | color: palette.white, 20 | marginTop: spacing.large, 21 | } 22 | 23 | const DESCRIPTION: TextStyle = { marginTop: spacing.large + spacing.tiny + spacing.tiny } 24 | 25 | const PANEL_BIO: ViewStyle = { flex: 1, marginTop: spacing.extraLarge + spacing.large } 26 | 27 | type RenderPanelProps = { event: Event } 28 | export const RenderPanel = (props: RenderPanelProps) => { 29 | const { image, title, description, speakers } = props.event 30 | 31 | const imageDimensions = calculateImageDimensions(getScreenWidth()) 32 | 33 | return ( 34 | 35 | {} 36 | 37 | 38 | {speakers && 39 | speakers.length && 40 | speakers.map((speaker, index) => { 41 | const isLast = index === speakers.length - 1 42 | return ( 43 | 44 | 45 | 46 | 47 | ) 48 | })} 49 | 50 | ) 51 | } 52 | -------------------------------------------------------------------------------- /app/screens/event-details/render-talk.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { View, ViewStyle } from "react-native" 3 | import Hyperlink from "react-native-hyperlink" 4 | import { SpeakerBio, TalkTitle, Text } from "../../components" 5 | import { SpeakerImage } from "../../components/speaker-image/speaker-image" 6 | import { Event } from "../../models" 7 | import { palette, spacing } from "../../theme" 8 | 9 | const FULL_SIZE: ViewStyle = { 10 | width: "100%", 11 | height: "100%", 12 | } 13 | 14 | type RenderTalkProps = { event: Event } 15 | 16 | export const RenderTalk = ({ event }: RenderTalkProps) => { 17 | return ( 18 | 19 | {event.speakers && } 20 | 21 | {event.description && ( 22 | 26 | 27 | {event.description} 28 | 29 | 30 | )} 31 | {event.speakers && } 32 | 33 | ) 34 | } 35 | -------------------------------------------------------------------------------- /app/screens/event-details/render-workshop.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { View, ViewStyle } from "react-native" 3 | import { SpeakerBio, SpeakerImage, TalkTitle } from "../../components" 4 | import { Event } from "../../models" 5 | 6 | const FULL_SIZE: ViewStyle = { 7 | width: "100%", 8 | height: "100%", 9 | } 10 | 11 | type RenderWorkshopProps = { event: Event } 12 | 13 | export function RenderWorkshop({ event }: RenderWorkshopProps) { 14 | return ( 15 | 16 | 17 | 18 | 19 | 20 | ) 21 | } 22 | -------------------------------------------------------------------------------- /app/screens/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./welcome/welcome-screen" 2 | export * from "./error/error-boundary" 3 | // export other screens here 4 | export * from "./venue/venue-screen" 5 | export * from "./schedule/schedule-screen" 6 | export * from "./code-of-conduct/code-of-conduct-screen" 7 | export * from "./event-details/event-details-screen" 8 | export * from "./info/info-screen" 9 | -------------------------------------------------------------------------------- /app/screens/info/info-screen.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useLayoutEffect } from "react" 2 | import { TextStyle } from "react-native" 3 | import { Text } from "../../components/text/text" 4 | import { Screen } from "../../components/screen/screen" 5 | import { palette, spacing } from "../../theme" 6 | import { PresentedBy } from "../../components/presented-by/presented-by" 7 | import { WiFi } from "../../components/wi-fi/wi-fi" 8 | import { Conduct } from "../../components/conduct/conduct" 9 | import { Sponsors } from "../../components/sponsors/sponsors" 10 | import { SurveyLink } from "../../components/survey-link/survey-link" 11 | import { useNavigation } from "@react-navigation/core" 12 | 13 | const TITLE: TextStyle = { 14 | marginTop: spacing.extraLarge, 15 | marginLeft: spacing.large, 16 | } 17 | 18 | export const InfoScreen = () => { 19 | const [renderFullContent, setRenderFullContent] = useState(false) 20 | const navigation = useNavigation() 21 | 22 | useLayoutEffect(() => { 23 | requestAnimationFrame(() => { 24 | setRenderFullContent(true) 25 | }) 26 | 27 | navigation.setOptions({ title: "Info" }) 28 | }, [navigation]) 29 | 30 | return ( 31 | 32 | 33 | 34 | navigation.navigate("infoCodeOfConduct")} /> 35 | 36 | {renderFullContent ? : null} 37 | 38 | 39 | ) 40 | } 41 | -------------------------------------------------------------------------------- /app/screens/schedule/render-event.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { useNavigation } from "@react-navigation/core" 3 | import { ScheduleCell } from "../../components" 4 | import { ScheduleCellPresetNames } from "../../components/schedule-cell/schedule-cell.presets" 5 | import { Event, useStores } from "../../models" 6 | import { observer } from "mobx-react-lite" 7 | 8 | type RenderEventProps = { event: Event; index: number } 9 | export const RenderEvent = observer(({ event, index }: RenderEventProps) => { 10 | const navigation = useNavigation() 11 | const { eventStore } = useStores() 12 | 13 | const eventType = event.eventType.toLowerCase() 14 | const cellPreset: ScheduleCellPresetNames = 15 | eventType === "break" || eventType === "afterparty" ? eventType : "default" 16 | 17 | return ( 18 | { 23 | eventStore.setCurrentEvent(event) 24 | navigation.navigate("eventDetails") 25 | }} 26 | key={index} 27 | /> 28 | ) 29 | }) 30 | -------------------------------------------------------------------------------- /app/screens/schedule/schedule-content.tsx: -------------------------------------------------------------------------------- 1 | import { observer } from "mobx-react-lite" 2 | import React from "react" 3 | import { TextStyle, View } from "react-native" 4 | import { Text } from "../../components" 5 | import { EventStore, EVENT_DAYS } from "../../models" 6 | import { color, spacing } from "../../theme" 7 | import { RenderEvent } from "./render-event" 8 | 9 | const SUBTITLE: TextStyle = { 10 | color: color.palette.white, 11 | fontWeight: "600", 12 | paddingHorizontal: spacing.large, 13 | marginTop: spacing.small, 14 | } 15 | const DATE: TextStyle = { 16 | fontStyle: "italic", 17 | fontWeight: "400", 18 | paddingHorizontal: spacing.large, 19 | marginBottom: spacing.small + spacing.large, 20 | } 21 | 22 | type ScheduleContentProps = { 23 | eventStore: EventStore 24 | selected: EVENT_DAYS 25 | } 26 | export const ScheduleContent = observer(({ eventStore, selected }: ScheduleContentProps) => { 27 | const selectedEvents = eventStore.eventsForDay(selected || "wednesday") 28 | 29 | return ( 30 | 31 | 40 | 49 | {selectedEvents && 50 | selectedEvents.map((event, index) => ( 51 | 52 | ))} 53 | 54 | ) 55 | }) 56 | -------------------------------------------------------------------------------- /app/screens/schedule/schedule-workshops.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { useNavigation } from "@react-navigation/core" 3 | import { TextStyle, View } from "react-native" 4 | import { ScheduleCell, Text } from "../../components" 5 | import { color, spacing } from "../../theme" 6 | import { Event, useStores } from "../../models" 7 | import { observer } from "mobx-react-lite" 8 | 9 | const SUBTITLE: TextStyle = { 10 | color: color.palette.white, 11 | fontWeight: "600", 12 | paddingHorizontal: spacing.large, 13 | marginTop: spacing.small, 14 | } 15 | const DATE: TextStyle = { 16 | fontStyle: "italic", 17 | fontWeight: "400", 18 | paddingHorizontal: spacing.large, 19 | marginBottom: spacing.small + spacing.large, 20 | } 21 | 22 | export const ScheduleWorkshops = observer(() => { 23 | const { eventStore } = useStores() 24 | const navigation = useNavigation() 25 | 26 | const { events } = eventStore 27 | const beginnerWorkshop = events.find((event) => event.track === "BEGINNER") 28 | const intermediateWorkshop = events.find((event) => event.track === "INTERMEDIATE") 29 | const advancedWorkshop = events.find((event) => event.track === "ADVANCED") 30 | const welcomeParty = events.find((event) => event.eventType === "afterparty") 31 | const onPressWorkshop = (event: Event) => { 32 | eventStore.setCurrentEvent(event) 33 | navigation.navigate("eventDetails") 34 | } 35 | 36 | return ( 37 | 38 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | ) 51 | }) 52 | -------------------------------------------------------------------------------- /app/screens/welcome/bg.welcome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/screens/welcome/bg.welcome.png -------------------------------------------------------------------------------- /app/screens/welcome/bg.welcome@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/screens/welcome/bg.welcome@2x.png -------------------------------------------------------------------------------- /app/screens/welcome/bg.welcome@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/app/screens/welcome/bg.welcome@3x.png -------------------------------------------------------------------------------- /app/screens/welcome/welcome-screen.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from "react" 2 | import { View, ViewStyle, TextStyle } from "react-native" 3 | import { StackScreenProps } from "@react-navigation/stack" 4 | import { observer } from "mobx-react-lite" 5 | import { Button, Footer, Screen, Text } from "../../components" 6 | import { spacing, palette } from "../../theme" 7 | import { NavigatorParamList } from "../../navigators" 8 | 9 | const backgroundImage = require("./bg.welcome.png") 10 | 11 | const ROOT: ViewStyle = { justifyContent: "space-between" } 12 | const TOP_CONTAINER: ViewStyle = { 13 | marginTop: spacing.large, 14 | } 15 | const HEADER1: TextStyle = { 16 | paddingHorizontal: spacing.large, 17 | marginTop: spacing.large, 18 | color: palette.white, 19 | } 20 | const HEADER2: TextStyle = { 21 | marginBottom: 38, 22 | paddingHorizontal: spacing.large, 23 | color: palette.offWhite, 24 | } 25 | const SUBHEADER: TextStyle = { 26 | paddingHorizontal: spacing.large, 27 | color: palette.offWhite, 28 | } 29 | 30 | export const WelcomeScreen: FC> = observer( 31 | ({ navigation }) => { 32 | const nextScreen = () => navigation.navigate("tabs") 33 | 34 | return ( 35 | 41 | 42 | 43 | 44 | 45 | 46 |
47 |
55 |
56 | ) 57 | }, 58 | ) 59 | -------------------------------------------------------------------------------- /app/services/api/api-config.ts: -------------------------------------------------------------------------------- 1 | // Use this import if you want to use "env.js" file 2 | // const { API_URL } = require("../../config/env") 3 | // Or just specify it directly like this: 4 | const API_URL = "http://example.com" 5 | 6 | /** 7 | * The options used to configure the API. 8 | */ 9 | export interface ApiConfig { 10 | /** 11 | * The URL of the api. 12 | */ 13 | url: string 14 | 15 | /** 16 | * Milliseconds before we timeout the request. 17 | */ 18 | timeout: number 19 | } 20 | 21 | /** 22 | * The default configuration for the app. 23 | */ 24 | export const DEFAULT_API_CONFIG: ApiConfig = { 25 | url: API_URL || "https://jsonplaceholder.typicode.com", 26 | timeout: 10000, 27 | } 28 | -------------------------------------------------------------------------------- /app/services/api/api.types.ts: -------------------------------------------------------------------------------- 1 | import { GeneralApiProblem } from "./api-problem" 2 | // import { Character } from "../../models/character/character" 3 | 4 | export interface User { 5 | id: number 6 | name: string 7 | } 8 | 9 | export type GetUsersResult = { kind: "ok"; users: User[] } | GeneralApiProblem 10 | export type GetUserResult = { kind: "ok"; user: User } | GeneralApiProblem 11 | 12 | export type GetCharactersResult = 13 | | { kind: "ok"; characters: /* Character */ unknown[] } 14 | | GeneralApiProblem 15 | export type GetCharacterResult = 16 | | { kind: "ok"; character: /* Character */ unknown } 17 | | GeneralApiProblem 18 | -------------------------------------------------------------------------------- /app/services/api/character-api.ts: -------------------------------------------------------------------------------- 1 | import { ApiResponse } from "apisauce" 2 | import { Api } from "./api" 3 | import { GetCharactersResult } from "./api.types" 4 | import { getGeneralApiProblem } from "./api-problem" 5 | 6 | const API_PAGE_SIZE = 50 7 | 8 | export class CharacterApi { 9 | private api: Api 10 | 11 | constructor(api: Api) { 12 | this.api = api 13 | } 14 | 15 | async getCharacters(): Promise { 16 | try { 17 | // make the api call 18 | const response: ApiResponse = await this.api.apisauce.get( 19 | "https://raw.githubusercontent.com/infinitered/ignite/master/data/rick-and-morty.json", 20 | { amount: API_PAGE_SIZE }, 21 | ) 22 | 23 | // the typical ways to die when calling an api 24 | if (!response.ok) { 25 | const problem = getGeneralApiProblem(response) 26 | if (problem) return problem 27 | } 28 | 29 | const characters = response.data.results 30 | 31 | return { kind: "ok", characters } 32 | } catch (e) { 33 | __DEV__ && console.tron.log(e.message) 34 | return { kind: "bad-data" } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/services/api/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./api" 2 | export * from "./api.types" 3 | -------------------------------------------------------------------------------- /app/services/reactotron/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./reactotron" 2 | -------------------------------------------------------------------------------- /app/services/reactotron/reactotron-config.ts: -------------------------------------------------------------------------------- 1 | export interface ReactotronConfig { 2 | /** The name of the app. */ 3 | name?: string 4 | /** The host to connect to: default 'localhost'. */ 5 | host?: string 6 | /** Should we use async storage */ 7 | useAsyncStorage?: boolean 8 | /** Should we clear Reactotron when load? */ 9 | clearOnLoad?: boolean 10 | /** Root state logging. */ 11 | state?: { 12 | /** log the initial data that we put into the state on startup? */ 13 | initial?: boolean 14 | /** log snapshot changes. */ 15 | snapshots?: boolean 16 | } 17 | } 18 | 19 | /** 20 | * The default Reactotron configuration. 21 | */ 22 | export const DEFAULT_REACTOTRON_CONFIG: ReactotronConfig = { 23 | clearOnLoad: true, 24 | host: "localhost", 25 | useAsyncStorage: true, 26 | state: { 27 | initial: true, 28 | snapshots: false, 29 | }, 30 | } 31 | -------------------------------------------------------------------------------- /app/services/reactotron/tron.ts: -------------------------------------------------------------------------------- 1 | import Reactotron from "reactotron-react-native" 2 | export const Tron = Reactotron 3 | -------------------------------------------------------------------------------- /app/services/reactotron/tron.web.ts: -------------------------------------------------------------------------------- 1 | import Reactotron from "reactotron-react-js" 2 | export const Tron = Reactotron 3 | -------------------------------------------------------------------------------- /app/theme/color.ts: -------------------------------------------------------------------------------- 1 | import { palette } from "./palette" 2 | 3 | /** 4 | * Roles for colors. Prefer using these over the palette. It makes it easier 5 | * to change things. 6 | * 7 | * The only roles we need to place in here are the ones that span through the app. 8 | * 9 | * If you have a specific use-case, like a spinner color. It makes more sense to 10 | * put that in the component. 11 | */ 12 | export const color = { 13 | /** 14 | * The palette is available to use, but prefer using the name. 15 | */ 16 | palette, 17 | /** 18 | * A helper for making something see-thru. Use sparingly as many layers of transparency 19 | * can cause older Android devices to slow down due to the excessive compositing required 20 | * by their under-powered GPUs. 21 | */ 22 | transparent: "rgba(0, 0, 0, 0)", 23 | /** 24 | * The screen background. 25 | */ 26 | background: palette.portGore, 27 | /** 28 | * The main tinting color. 29 | */ 30 | primary: palette.crimson, 31 | /** 32 | * The main tinting color, but darker. 33 | */ 34 | primaryDarker: palette.portGore, 35 | /** 36 | * A subtle color used for borders and lines. 37 | */ 38 | line: palette.offWhite, 39 | /** 40 | * The default color of text in many components. 41 | */ 42 | text: palette.white, 43 | /** 44 | * Secondard information. 45 | */ 46 | dim: palette.lightGrey, 47 | /** 48 | * Error messages and icons. 49 | */ 50 | error: palette.angry, 51 | tabbar: palette.ebony, 52 | callout: palette.purple, 53 | calloutShadow: palette.darkPurple, 54 | } 55 | -------------------------------------------------------------------------------- /app/theme/fonts/index.ts: -------------------------------------------------------------------------------- 1 | // import * as Font from "expo-font" 2 | 3 | export const initFonts = async () => { 4 | // Refer to ./assets/fonts/custom-fonts.md for instructions. 5 | // ... 6 | // Welcome back! Just uncomment this and replace/append with your font file names! 7 | // ⬇ 8 | // await Font.loadAsync({ 9 | // Montserrat: require("./Montserrat-Regular.ttf"), 10 | // "Montserrat-Regular": require("./Montserrat-Regular.ttf"), 11 | // }) 12 | } 13 | -------------------------------------------------------------------------------- /app/theme/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./spacing" 2 | export * from "./typography" 3 | export * from "./timing" 4 | export * from "./palette" 5 | export * from "./color" 6 | -------------------------------------------------------------------------------- /app/theme/palette.ts: -------------------------------------------------------------------------------- 1 | export const palette = { 2 | orange:'#FF8000', 3 | black: "#1d1d1d", 4 | white: "#ffffff", 5 | offWhite: "#C7C4DB", 6 | crimson: "#EC174F", 7 | ebony: "#10102A", 8 | portGore: "#161637", 9 | portGoreLight: "#1B1840", 10 | portGoreLighter: "#201B48", 11 | waterloo: "#878794", 12 | martinique: "#2C2C4C", 13 | mantiniqueLight: "#36325a", 14 | shamrock: "#56E39F", 15 | vintageRock: "rgba(86,227,159,0.20)", 16 | lightGrey: "#E6EAF4", 17 | lighterGrey: "#CDD4DA", 18 | haiti: "#0F0F30", 19 | angry: "#dd3333", 20 | purple: "#6600FF", 21 | darkPurple: "#0F0F30", 22 | } 23 | -------------------------------------------------------------------------------- /app/theme/spacing.ts: -------------------------------------------------------------------------------- 1 | import { Dimensions } from "react-native" 2 | 3 | export const spacing = { 4 | tiny: 4, 5 | small: 10, 6 | medium: 14, 7 | large: 20, 8 | extraLarge: 43, 9 | huge: 80, 10 | ginormous: 100, 11 | } 12 | 13 | export const textSizes = { 14 | title: 24, 15 | } 16 | 17 | export const getScreenWidth = () => Dimensions.get("window").width 18 | export const getScreenHeight = () => Dimensions.get("window").height 19 | 20 | export const HIT_SLOP = { 21 | top: 20, 22 | left: 20, 23 | right: 20, 24 | bottom: 20, 25 | } 26 | -------------------------------------------------------------------------------- /app/theme/timing.ts: -------------------------------------------------------------------------------- 1 | export const timing = { 2 | /** 3 | * The duration (ms) for quick animations. 4 | */ 5 | quick: 300, 6 | } 7 | -------------------------------------------------------------------------------- /app/theme/typography.ts: -------------------------------------------------------------------------------- 1 | import { Platform } from "react-native" 2 | 3 | /** 4 | * You can find a list of available fonts on both iOS and Android here: 5 | * https://github.com/react-native-training/react-native-fonts 6 | * 7 | * If you're interested in adding a custom font to your project, 8 | * check out the readme file in ./assets/fonts/ then come back here 9 | * and enter your new font name. Remember the Android font name 10 | * is probably different than iOS. 11 | * More on that here: 12 | * https://github.com/lendup/react-native-cross-platform-text 13 | * 14 | * The various styles of fonts are defined in the component. 15 | */ 16 | export const typography = { 17 | /** 18 | * The primary font. Used in most places. 19 | */ 20 | primary: Platform.select({ ios: "Helvetica", android: "normal" }), 21 | 22 | /** 23 | * An alternate font used for perhaps titles and stuff. 24 | */ 25 | secondary: Platform.select({ ios: "Arial", android: "sans-serif" }), 26 | 27 | /** 28 | * Lets get fancy with a monospace font! 29 | */ 30 | code: Platform.select({ ios: "Courier", android: "monospace" }), 31 | } 32 | -------------------------------------------------------------------------------- /app/utils/delay.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * A "modern" sleep statement. 3 | * 4 | * @param ms The number of milliseconds to wait. 5 | */ 6 | export const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) 7 | -------------------------------------------------------------------------------- /app/utils/ignore-warnings.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Ignore some yellowbox warnings. Some of these are for deprecated functions 3 | * that we haven't gotten around to replacing yet. 4 | */ 5 | import { LogBox } from "react-native" 6 | 7 | // prettier-ignore 8 | LogBox.ignoreLogs([ 9 | "Require cycle:", 10 | ]) 11 | -------------------------------------------------------------------------------- /app/utils/info.ts: -------------------------------------------------------------------------------- 1 | export const TIMEZONE = "America/Los_Angeles" 2 | -------------------------------------------------------------------------------- /app/utils/keychain.ts: -------------------------------------------------------------------------------- 1 | import * as ReactNativeKeychain from "react-native-keychain" 2 | 3 | /** 4 | * Saves some credentials securely. 5 | * 6 | * @param username The username 7 | * @param password The password 8 | * @param server The server these creds are for. 9 | */ 10 | export async function save(username: string, password: string, server?: string) { 11 | if (server) { 12 | await ReactNativeKeychain.setInternetCredentials(server, username, password) 13 | return true 14 | } else { 15 | return ReactNativeKeychain.setGenericPassword(username, password) 16 | } 17 | } 18 | 19 | /** 20 | * Loads credentials that were already saved. 21 | * 22 | * @param server The server that these creds are for 23 | */ 24 | export async function load(server?: string) { 25 | if (server) { 26 | const creds = await ReactNativeKeychain.getInternetCredentials(server) 27 | return { 28 | username: creds ? creds.username : null, 29 | password: creds ? creds.password : null, 30 | server, 31 | } 32 | } else { 33 | const creds = await ReactNativeKeychain.getGenericPassword() 34 | if (typeof creds === "object") { 35 | return { 36 | username: creds.username, 37 | password: creds.password, 38 | server: null, 39 | } 40 | } else { 41 | return { 42 | username: null, 43 | password: null, 44 | server: null, 45 | } 46 | } 47 | } 48 | } 49 | 50 | /** 51 | * Resets any existing credentials for the given server. 52 | * 53 | * @param server The server which has these creds 54 | */ 55 | export async function reset(server?: string) { 56 | if (server) { 57 | await ReactNativeKeychain.resetInternetCredentials(server) 58 | return true 59 | } else { 60 | const result = await ReactNativeKeychain.resetGenericPassword() 61 | return result 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /app/utils/storage/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./storage" 2 | -------------------------------------------------------------------------------- /app/utils/storage/storage.test.ts: -------------------------------------------------------------------------------- 1 | import AsyncStorage from "@react-native-async-storage/async-storage" 2 | import { load, loadString, save, saveString, clear, remove } from "./storage" 3 | 4 | // fixtures 5 | const VALUE_OBJECT = { x: 1 } 6 | const VALUE_STRING = JSON.stringify(VALUE_OBJECT) 7 | 8 | beforeEach(() => (AsyncStorage.getItem as jest.Mock).mockReturnValue(Promise.resolve(VALUE_STRING))) 9 | afterEach(() => jest.clearAllMocks()) 10 | 11 | test("load", async () => { 12 | const value = await load("something") 13 | expect(value).toEqual(JSON.parse(VALUE_STRING)) 14 | }) 15 | 16 | test("loadString", async () => { 17 | const value = await loadString("something") 18 | expect(value).toEqual(VALUE_STRING) 19 | }) 20 | 21 | test("save", async () => { 22 | await save("something", VALUE_OBJECT) 23 | expect(AsyncStorage.setItem).toHaveBeenCalledWith("something", VALUE_STRING) 24 | }) 25 | 26 | test("saveString", async () => { 27 | await saveString("something", VALUE_STRING) 28 | expect(AsyncStorage.setItem).toHaveBeenCalledWith("something", VALUE_STRING) 29 | }) 30 | 31 | test("remove", async () => { 32 | await remove("something") 33 | expect(AsyncStorage.removeItem).toHaveBeenCalledWith("something") 34 | }) 35 | 36 | test("clear", async () => { 37 | await clear() 38 | expect(AsyncStorage.clear).toHaveBeenCalledWith() 39 | }) 40 | -------------------------------------------------------------------------------- /app/utils/storage/storage.ts: -------------------------------------------------------------------------------- 1 | import AsyncStorage from "@react-native-async-storage/async-storage" 2 | 3 | /** 4 | * Loads a string from storage. 5 | * 6 | * @param key The key to fetch. 7 | */ 8 | export async function loadString(key: string): Promise { 9 | try { 10 | return await AsyncStorage.getItem(key) 11 | } catch { 12 | // not sure why this would fail... even reading the RN docs I'm unclear 13 | return null 14 | } 15 | } 16 | 17 | /** 18 | * Saves a string to storage. 19 | * 20 | * @param key The key to fetch. 21 | * @param value The value to store. 22 | */ 23 | export async function saveString(key: string, value: string): Promise { 24 | try { 25 | await AsyncStorage.setItem(key, value) 26 | return true 27 | } catch { 28 | return false 29 | } 30 | } 31 | 32 | /** 33 | * Loads something from storage and runs it thru JSON.parse. 34 | * 35 | * @param key The key to fetch. 36 | */ 37 | export async function load(key: string): Promise { 38 | try { 39 | const almostThere = await AsyncStorage.getItem(key) 40 | return JSON.parse(almostThere) 41 | } catch { 42 | return null 43 | } 44 | } 45 | 46 | /** 47 | * Saves an object to storage. 48 | * 49 | * @param key The key to fetch. 50 | * @param value The value to store. 51 | */ 52 | export async function save(key: string, value: any): Promise { 53 | try { 54 | await AsyncStorage.setItem(key, JSON.stringify(value)) 55 | return true 56 | } catch { 57 | return false 58 | } 59 | } 60 | 61 | /** 62 | * Removes something from storage. 63 | * 64 | * @param key The key to kill. 65 | */ 66 | export async function remove(key: string): Promise { 67 | try { 68 | await AsyncStorage.removeItem(key) 69 | } catch {} 70 | } 71 | 72 | /** 73 | * Burn it all to the ground. 74 | */ 75 | export async function clear(): Promise { 76 | try { 77 | await AsyncStorage.clear() 78 | } catch {} 79 | } 80 | -------------------------------------------------------------------------------- /assets/images/adaptive-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/assets/images/adaptive-icon.png -------------------------------------------------------------------------------- /assets/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/assets/images/favicon.png -------------------------------------------------------------------------------- /assets/images/icon-default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/assets/images/icon-default.png -------------------------------------------------------------------------------- /assets/images/icon-ios.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/assets/images/icon-ios.png -------------------------------------------------------------------------------- /assets/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/assets/images/icon.png -------------------------------------------------------------------------------- /assets/images/splash-tablet-landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/assets/images/splash-tablet-landscape.png -------------------------------------------------------------------------------- /assets/images/splash-tablet-portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/assets/images/splash-tablet-portrait.png -------------------------------------------------------------------------------- /assets/images/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinitered/ChainReactApp2022/712d48c73f55f33298c3d3e089df670f9488a375/assets/images/splash.png -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ["babel-preset-expo"], 3 | env: { 4 | production: {}, 5 | }, 6 | plugins: [ 7 | [ 8 | "@babel/plugin-proposal-decorators", 9 | { 10 | legacy: true, 11 | }, 12 | ], 13 | ["@babel/plugin-proposal-optional-catch-binding"], 14 | ], 15 | } 16 | -------------------------------------------------------------------------------- /bin/downloadExpoApp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | set -euo pipefail 4 | 5 | # based on https://github.com/yaron1m/expo-detox-typescript-example/blob/master/scripts/dl_expo_bins 6 | APP_PATH=./bin/Exponent.app 7 | 8 | if [ ! -d $APP_PATH ]; then 9 | echo "First time running Detox -- downloading Expo client app" 10 | 11 | # Sanity check 12 | if [ ! -f "package.json" ]; then 13 | echo "Oops - run this command from your project's root folder" >>/dev/stderr 14 | exit 1 15 | fi 16 | 17 | # Make the app dir (this'll also make sure we already have the bin directory) 18 | mkdir $APP_PATH 19 | 20 | # query expo.io to find most recent ipaUrl 21 | IPA_URL=`curl --silent --show-error https://expo.io/--/api/v2/versions | python -c 'import sys, json; print json.load(sys.stdin)["iosUrl"]'` 22 | 23 | # download tar.gz 24 | TMP_PATH=./exponent.tar.gz 25 | curl --silent --show-error --output $TMP_PATH $IPA_URL 26 | 27 | # unzip tar.gz into APP_PATH 28 | tar -C $APP_PATH -xzf $TMP_PATH 29 | rm ./exponent.tar.gz 30 | fi 31 | -------------------------------------------------------------------------------- /bin/postInstall: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const childProcess = require("child_process") 4 | const os = require("os") 5 | 6 | /** 7 | * Do all things that need to be done after installing packages 8 | * 9 | * Yes, it slows down package installation a little, but it's nice to not 10 | * have to remember these extra steps. 11 | */ 12 | ;[ 13 | // Patch all the necessary modules. 14 | { command: "npx patch-package" }, 15 | 16 | // Make sure we're set up correctly 17 | { command: "solidarity" }, 18 | 19 | // Kill the metro bundler if it's running. 20 | { command: 'pkill -f "cli.js start" || set exit 0', onlyPlatforms: ["darwin", "linux"] }, 21 | // Help wanted: Add the windows version here. { command: "????", onlyPlatforms: ["win32"] }, 22 | 23 | // Make sure our native modules are androidX-happy 24 | { command: "jetify" }, 25 | 26 | // on iOS, make sure our native modules are installed 27 | { command: "pod install", cwd: "ios", onlyPlatforms: ["darwin"] }, 28 | ] 29 | .filter(({ onlyPlatforms }) => !onlyPlatforms || onlyPlatforms.includes(os.platform())) 30 | .forEach((commandAndOptions) => { 31 | const { command, onlyPlatform: _, ...options } = commandAndOptions 32 | try { 33 | childProcess.execSync(command, { 34 | stdio: "inherit", 35 | ...options, 36 | }) 37 | } catch (error) { 38 | process.exit(error.status) 39 | } 40 | }) 41 | -------------------------------------------------------------------------------- /e2e/README.md: -------------------------------------------------------------------------------- 1 | # Detox End-To-End Testing 2 | 3 | ## Setup 4 | 5 | To get your Detox tests up and running, you'll need to install some global dependencies: 6 | 7 | 1. Install the latest version of [Homebrew](https://brew.sh/) 8 | 2. Make sure you have Node installed (at least 8.6.0). If you don't: 9 | 10 | If you use NVM: 11 | 12 | ```bash 13 | nvm install node 14 | ``` 15 | 16 | Or if you'd prefer to install directly from Homebrew 17 | 18 | ```bash 19 | brew update && brew install node 20 | ``` 21 | 22 | 3. Install `applesimutils, which will allow Detox to communicate with the iOS simulator: 23 | 24 | ```bash 25 | brew tap wix/brew && brew install applesimutils 26 | ``` 27 | 28 | 4. Install the Detox CLI 29 | 30 | ```bash 31 | yarn global add detox-cli 32 | ``` 33 | 34 | ## Adding tests 35 | 36 | We've gotten you started with `./e2e/firstTest.spec.js`, which tests that the two main example screens render properly. 37 | 38 | Note that in order to pick up elements by ID, we've added the `testID` prop to the component. 39 | 40 | ## Running tests 41 | 42 | 1. Start the packager 43 | 44 | ``` 45 | yarn start 46 | ``` 47 | 48 | _(Expo-only note: for testing [production code](https://docs.expo.io/workflow/development-mode/#production-mode), start the packager with `yarn start --no-dev --minify`)_ 49 | 50 | 2. Run the app 51 | 52 | In a separate terminal window from the packager: 53 | 54 | ``` 55 | yarn build:e2e 56 | ``` 57 | 58 | _(Expo-only note: this is unnecessary for Expo apps)_ 59 | 60 | 3. Run the tests 61 | 62 | ``` 63 | yarn test:e2e 64 | ``` 65 | 66 | For more information, make sure to check out the official [Detox Docs](https://github.com/wix/Detox/blob/master/docs/README.md) 67 | -------------------------------------------------------------------------------- /e2e/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "setupFilesAfterEnv": ["./init.js"], 3 | "testEnvironment": "node" 4 | } 5 | -------------------------------------------------------------------------------- /e2e/firstTest.spec.js: -------------------------------------------------------------------------------- 1 | // For more info on how to write Detox tests, see the official docs: 2 | // https://github.com/wix/Detox/blob/master/docs/README.md 3 | 4 | const { reloadApp } = require("./reload") 5 | 6 | describe("Example", () => { 7 | beforeEach(async () => { 8 | await reloadApp() 9 | }) 10 | 11 | it("should have welcome screen", async () => { 12 | await expect(element(by.id("WelcomeScreen"))).toBeVisible() 13 | }) 14 | 15 | it("should go to next screen after tap", async () => { 16 | await element(by.id("next-screen-button")).tap() 17 | await expect(element(by.id("DemoScreen"))).toBeVisible() 18 | }) 19 | }) 20 | -------------------------------------------------------------------------------- /e2e/init.js: -------------------------------------------------------------------------------- 1 | const detox = require("detox") 2 | const config = require("../package.json").detox 3 | const adapter = require("detox/runners/jest/adapter") 4 | 5 | jest.setTimeout(120000) 6 | jasmine.getEnv().addReporter(adapter) 7 | 8 | beforeAll(async () => { 9 | await detox.init(config) 10 | }) 11 | 12 | beforeEach(async () => { 13 | await adapter.beforeEach() 14 | }) 15 | 16 | afterAll(async () => { 17 | await adapter.afterAll() 18 | await detox.cleanup() 19 | }) 20 | -------------------------------------------------------------------------------- /e2e/reload.js: -------------------------------------------------------------------------------- 1 | const { reloadApp } = require("detox-expo-helpers") 2 | module.exports = { reloadApp } 3 | -------------------------------------------------------------------------------- /eas.json: -------------------------------------------------------------------------------- 1 | { 2 | "build": { 3 | "production": {}, 4 | "development": { 5 | "developmentClient": true, 6 | "distribution": "internal" 7 | } 8 | }, 9 | "submit": { 10 | "production": {} 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /ignite/templates/component/NAME.story.tsx.ejs: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { storiesOf } from "@storybook/react-native" 3 | import { StoryScreen, Story, UseCase } from "../../../storybook/views" 4 | import { color } from "../../theme" 5 | import { <%= props.pascalCaseName %> } from "./<%= props.kebabCaseName %>" 6 | 7 | storiesOf("<%= props.pascalCaseName %>", module) 8 | .addDecorator((fn) => {fn()}) 9 | .add("Style Presets", () => ( 10 | 11 | 12 | <<%= props.pascalCaseName %> style={{ backgroundColor: color.error }} /> 13 | 14 | 15 | )) 16 | -------------------------------------------------------------------------------- /ignite/templates/component/NAME.tsx.ejs: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { StyleProp, TextStyle, View, ViewStyle } from "react-native" 3 | import { observer } from "mobx-react-lite" 4 | import { color, typography } from "../../theme" 5 | import { Text } from "../" 6 | import { flatten } from "ramda" 7 | 8 | const CONTAINER: ViewStyle = { 9 | justifyContent: "center", 10 | } 11 | 12 | const TEXT: TextStyle = { 13 | fontFamily: typography.primary, 14 | fontSize: 14, 15 | color: color.primary, 16 | } 17 | 18 | export interface <%= props.pascalCaseName %>Props { 19 | /** 20 | * An optional style override useful for padding & margin. 21 | */ 22 | style?: StyleProp 23 | } 24 | 25 | /** 26 | * Describe your component here 27 | */ 28 | export const <%= props.pascalCaseName %> = observer(function <%= props.pascalCaseName %>(props: <%= props.pascalCaseName %>Props) { 29 | const { style } = props 30 | const styles = flatten([CONTAINER, style]) 31 | 32 | return ( 33 | 34 | Hello 35 | 36 | ) 37 | }) 38 | -------------------------------------------------------------------------------- /ignite/templates/model/NAME.test.ts.ejs: -------------------------------------------------------------------------------- 1 | import { <%= props.pascalCaseName %>Model } from "./<%= props.kebabCaseName %>" 2 | 3 | test("can be created", () => { 4 | const instance = <%= props.pascalCaseName %>Model.create({}) 5 | 6 | expect(instance).toBeTruthy() 7 | }) 8 | -------------------------------------------------------------------------------- /ignite/templates/model/NAME.ts.ejs: -------------------------------------------------------------------------------- 1 | import { Instance, SnapshotOut, types } from "mobx-state-tree" 2 | 3 | /** 4 | * Model description here for TypeScript hints. 5 | */ 6 | export const <%= props.pascalCaseName %>Model = types 7 | .model("<%= props.pascalCaseName %>") 8 | .props({}) 9 | .views((self) => ({})) // eslint-disable-line @typescript-eslint/no-unused-vars 10 | .actions((self) => ({})) // eslint-disable-line @typescript-eslint/no-unused-vars 11 | 12 | type <%= props.pascalCaseName %>Type = InstanceModel> 13 | export interface <%= props.pascalCaseName %> extends <%= props.pascalCaseName %>Type {} 14 | type <%= props.pascalCaseName %>SnapshotType = SnapshotOutModel> 15 | export interface <%= props.pascalCaseName %>Snapshot extends <%= props.pascalCaseName %>SnapshotType {} 16 | export const create<%= props.pascalCaseName %>DefaultModel = () => types.optional(<%= props.pascalCaseName %>Model, {}) 17 | -------------------------------------------------------------------------------- /ignite/templates/navigator/NAME-navigator.tsx.ejs: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { createStackNavigator } from "@react-navigation/stack" 3 | import { 4 | DemoScreen 5 | } from "../../screens" 6 | 7 | export type <%= props.pascalCaseName %>ParamList = { 8 | demo: undefined 9 | } 10 | 11 | const Stack = createStackNavigator<<%= props.pascalCaseName %>ParamList>() 12 | export const <%= props.pascalCaseName %> = () => { 13 | return ( 14 | 15 | 16 | 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /ignite/templates/screen/NAME-screen.tsx.ejs: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { observer } from "mobx-react-lite" 3 | import { ViewStyle } from "react-native" 4 | import { Screen, Text } from "../../components" 5 | // import { useNavigation } from "@react-navigation/native" 6 | // import { useStores } from "../../models" 7 | import { color } from "../../theme" 8 | 9 | const ROOT: ViewStyle = { 10 | backgroundColor: color.palette.black, 11 | flex: 1, 12 | } 13 | 14 | export const <%= props.pascalCaseName %>Screen = observer(function <%= props.pascalCaseName %>Screen() { 15 | // Pull in one of our MST stores 16 | // const { someStore, anotherStore } = useStores() 17 | 18 | // Pull in navigation via hook 19 | // const navigation = useNavigation() 20 | return ( 21 | 22 | 23 | 24 | ) 25 | }) 26 | -------------------------------------------------------------------------------- /react-native.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | assets: ["./assets/fonts/"], 3 | } 4 | -------------------------------------------------------------------------------- /storybook/index.ts: -------------------------------------------------------------------------------- 1 | // this is the native storybook entry point 2 | // import { StorybookUI } from "./config" 3 | 4 | export * from "./storybook" 5 | -------------------------------------------------------------------------------- /storybook/storybook-registry.ts: -------------------------------------------------------------------------------- 1 | require("../app/components/text/text.story") 2 | require("../app/components/auto-image/auto-image.story") 3 | require("../app/components/button/button.story") 4 | require("../app/components/form-row/form-row.story") 5 | require("../app/components/switch/switch.story") 6 | require("../app/components/text-field/text-field.story") 7 | require("../app/components/checkbox/checkbox.story") 8 | require("../app/components/wallpaper/wallpaper.story") 9 | require("../app/components/gradient-background/gradient-background.story") 10 | require("../app/components/icon/icon.story") 11 | require("../app/components/header/header.story") 12 | -------------------------------------------------------------------------------- /storybook/storybook.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from "react" 2 | import { getStorybookUI, configure } from "@storybook/react-native" 3 | import { initFonts } from "../app/theme/fonts" 4 | 5 | declare let module 6 | 7 | configure(() => { 8 | require("./storybook-registry") 9 | }, module) 10 | 11 | const StorybookUI = getStorybookUI({ 12 | port: 9001, 13 | host: "localhost", 14 | onDeviceUI: true, 15 | asyncStorage: require("@react-native-async-storage/async-storage").default || null, 16 | }) 17 | 18 | export function StorybookUIRoot() { 19 | useEffect(() => { 20 | ;(async () => { 21 | await initFonts() // expo only 22 | if (typeof __TEST__ === "undefined" || !__TEST__) { 23 | const Reactotron = require("../app/services/reactotron") 24 | const reactotron = new Reactotron.Reactotron() 25 | reactotron.setup() 26 | } 27 | })() 28 | }, []) 29 | 30 | return 31 | } 32 | -------------------------------------------------------------------------------- /storybook/toggle-storybook.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from "react" 2 | import { DevSettings } from "react-native" 3 | import { loadString, saveString } from "../app/utils/storage" 4 | 5 | /** 6 | * Toggle Storybook mode, in __DEV__ mode only. 7 | * 8 | * In non-__DEV__ mode, or when Storybook isn't toggled on, 9 | * renders its children. 10 | * 11 | * The mode flag is persisted in async storage, which means it 12 | * persists across reloads/restarts - this is handy when developing 13 | * new components in Storybook. 14 | */ 15 | export function ToggleStorybook(props) { 16 | const [showStorybook, setShowStorybook] = useState(false) 17 | const [StorybookUIRoot, setStorybookUIRoot] = useState(null) 18 | 19 | useEffect(() => { 20 | if (__DEV__ && DevSettings) { 21 | // Load the setting from storage if it's there 22 | loadString("devStorybook").then((storedSetting) => { 23 | // Set the initial value 24 | setShowStorybook(storedSetting === "on") 25 | 26 | // Add our toggle command to the menu 27 | DevSettings.addMenuItem("Toggle Storybook", () => { 28 | setShowStorybook((show) => { 29 | // On toggle, flip the current value 30 | show = !show 31 | 32 | // Write it back to storage 33 | saveString("devStorybook", show ? "on" : "off") 34 | 35 | // Return it to change the local state 36 | return show 37 | }) 38 | }) 39 | 40 | // Load the storybook UI once 41 | setStorybookUIRoot(() => require("./storybook").StorybookUIRoot) 42 | }) 43 | } 44 | }, []) 45 | 46 | if (showStorybook) { 47 | return StorybookUIRoot ? : null 48 | } else { 49 | return props.children 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /storybook/toggle-storybook.web.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from "react" 2 | import * as QueryString from "query-string" 3 | 4 | interface StorybookQueryParams { 5 | storybook?: boolean 6 | } 7 | 8 | export const ToggleStorybook = (props) => { 9 | const [StorybookUIRoot, setStorybookUIRoot] = useState(null) 10 | const [queryParams, setQueryParams] = useState({}) 11 | 12 | useEffect(() => { 13 | if (__DEV__) { 14 | // Load the storybook UI once 15 | setStorybookUIRoot(() => require("./storybook").StorybookUIRoot) 16 | } 17 | }, []) 18 | 19 | useEffect(() => { 20 | if (__DEV__) { 21 | setQueryParams(QueryString.parse(window.location.search)) 22 | } 23 | }, [window.location.search]) 24 | 25 | if (queryParams?.storybook) { 26 | return StorybookUIRoot ? : null 27 | } else { 28 | return props.children 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /storybook/views/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./story-screen" 2 | export * from "./story" 3 | export * from "./use-case" 4 | -------------------------------------------------------------------------------- /storybook/views/story-screen.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { ViewStyle, KeyboardAvoidingView, Platform } from "react-native" 3 | 4 | const ROOT: ViewStyle = { backgroundColor: "#f0f0f0", flex: 1 } 5 | 6 | export interface StoryScreenProps { 7 | children?: React.ReactNode 8 | } 9 | 10 | const behavior = Platform.OS === "ios" ? "padding" : undefined 11 | export const StoryScreen = (props: StoryScreenProps) => ( 12 | 13 | {props.children} 14 | 15 | ) 16 | -------------------------------------------------------------------------------- /storybook/views/story.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { ScrollView, View, ViewStyle } from "react-native" 3 | 4 | export interface StoryProps { 5 | children?: React.ReactNode 6 | } 7 | 8 | const ROOT: ViewStyle = { flex: 1 } 9 | 10 | export function Story(props: StoryProps) { 11 | return ( 12 | 13 | {props.children} 14 | 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /test/mock-async-storage.ts: -------------------------------------------------------------------------------- 1 | import mockAsyncStorage from "@react-native-async-storage/async-storage/jest/async-storage-mock" 2 | 3 | jest.mock("@react-native-async-storage/async-storage", () => mockAsyncStorage) 4 | -------------------------------------------------------------------------------- /test/mock-file.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | height: 100, 3 | width: 100, 4 | scale: 2.0, 5 | uri: "https://placekitten.com/200/200", 6 | } 7 | -------------------------------------------------------------------------------- /test/mock-i18n.ts: -------------------------------------------------------------------------------- 1 | jest.mock("i18n-js", () => { 2 | return { 3 | t: (key) => `${key}.test`, 4 | } 5 | }) 6 | -------------------------------------------------------------------------------- /test/mock-react-native-image.ts: -------------------------------------------------------------------------------- 1 | import * as ReactNative from "react-native" 2 | import mockFile from "./mock-file" 3 | 4 | jest.doMock("react-native", () => { 5 | // Extend ReactNative 6 | return Object.setPrototypeOf( 7 | { 8 | Image: { 9 | ...ReactNative.Image, 10 | resolveAssetSource: jest.fn((source) => mockFile), // eslint-disable-line @typescript-eslint/no-unused-vars 11 | getSize: jest.fn( 12 | ( 13 | uri: string, // eslint-disable-line @typescript-eslint/no-unused-vars 14 | success: (width: number, height: number) => void, 15 | failure?: (error: any) => void, // eslint-disable-line @typescript-eslint/no-unused-vars 16 | ) => success(100, 100), 17 | ), 18 | }, 19 | }, 20 | ReactNative, 21 | ) 22 | }) 23 | -------------------------------------------------------------------------------- /test/mock-reactotron.ts: -------------------------------------------------------------------------------- 1 | declare const tron // eslint-disable-line @typescript-eslint/no-unused-vars 2 | -------------------------------------------------------------------------------- /test/setup.ts: -------------------------------------------------------------------------------- 1 | // we always make sure 'react-native' gets included first 2 | import "react-native" 3 | 4 | // libraries to mock 5 | import "./mock-react-native-image" 6 | import "./mock-async-storage" 7 | import "./mock-i18n" 8 | import "./mock-reactotron" 9 | 10 | jest.useFakeTimers() 11 | declare global { 12 | let __TEST__ 13 | } 14 | -------------------------------------------------------------------------------- /test/storyshots.test.ts: -------------------------------------------------------------------------------- 1 | import initStoryshots from "@storybook/addon-storyshots" 2 | 3 | initStoryshots({ 4 | configPath: "./storybook", 5 | framework: "react-native", 6 | }) 7 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowJs": false, 4 | "allowSyntheticDefaultImports": true, 5 | "experimentalDecorators": true, 6 | "jsx": "react-native", 7 | "module": "es2015", 8 | "moduleResolution": "node", 9 | "noImplicitAny": false, 10 | "noImplicitReturns": true, 11 | "noImplicitThis": true, 12 | "noUnusedLocals": true, 13 | "sourceMap": true, 14 | "target": "esnext", 15 | "lib": [ 16 | "esnext", 17 | "dom" 18 | ], 19 | "skipLibCheck": true, 20 | "resolveJsonModule": true 21 | }, 22 | "exclude": [ 23 | "node_modules" 24 | ], 25 | "include": [ 26 | "App.js", 27 | "app", 28 | "test", 29 | "storybook" 30 | ], 31 | "extends": "expo/tsconfig.base" 32 | } 33 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const createExpoWebpackConfigAsync = require("@expo/webpack-config") 2 | 3 | // Expo CLI will await this method so you can optionally return a promise. 4 | module.exports = async function (env, argv) { 5 | const config = await createExpoWebpackConfigAsync(env, argv) 6 | // If you want to add a new alias to the config. 7 | // config.resolve.alias["moduleA"] = "moduleB" 8 | 9 | // Maybe you want to turn off compression in dev mode. 10 | if (config.mode === "development") { 11 | config.devServer.compress = false 12 | } 13 | 14 | // Or prevent minimizing the bundle when you build. 15 | // if (config.mode === "production") { 16 | // config.optimization.minimize = false 17 | // } 18 | 19 | // Finally return the new config for the CLI to use. 20 | return config 21 | } 22 | --------------------------------------------------------------------------------