├── .eslintrc.js ├── .gitignore ├── .npmignore ├── .nvmrc ├── ISSUE_TEMPLATE.md ├── LICENSE ├── README.md ├── ToggleCalendar ├── .buckconfig ├── .eslintrc.js ├── .flowconfig ├── .gitattributes ├── .gitignore ├── .prettierrc.js ├── .watchmanconfig ├── __tests__ │ └── App-test.js ├── android │ ├── app │ │ ├── BUCK │ │ ├── build.gradle │ │ ├── build_defs.bzl │ │ ├── debug.keystore │ │ ├── proguard-rules.pro │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── togglecalendar │ │ │ │ ├── MainActivity.java │ │ │ │ └── MainApplication.java │ │ │ └── res │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ └── values │ │ │ ├── strings.xml │ │ │ └── styles.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle ├── app.json ├── babel.config.js ├── index.js ├── ios │ ├── Podfile │ ├── ToggleCalendar-tvOS │ │ └── Info.plist │ ├── ToggleCalendar-tvOSTests │ │ └── Info.plist │ ├── ToggleCalendar.xcodeproj │ │ ├── project.pbxproj │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ ├── ToggleCalendar-tvOS.xcscheme │ │ │ └── ToggleCalendar.xcscheme │ ├── ToggleCalendar │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Base.lproj │ │ │ └── LaunchScreen.xib │ │ ├── Images.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Info.plist │ │ └── main.m │ └── ToggleCalendarTests │ │ ├── Info.plist │ │ └── ToggleCalendarTests.m ├── metro.config.js ├── package.json └── src │ ├── App.js │ ├── components │ ├── CalendarDayComponent.js │ ├── CalendarFooterComponent.js │ └── CalendarHeaderComponent.js │ └── images │ ├── arrow.png │ ├── grid.png │ ├── high-demand.png │ └── list.png ├── demo ├── agenda.gif ├── calendar-list.gif ├── calendar.gif ├── custom.png ├── horizontal-calendar-list.gif ├── loader.png ├── marking1.png ├── marking2.png ├── marking3.png ├── marking4.png ├── marking5.png └── marking6.png ├── example ├── .babelrc ├── .buckconfig ├── .flowconfig ├── .gitattributes ├── .gitignore ├── .watchmanconfig ├── __tests__ │ ├── index.android.js │ └── index.ios.js ├── android │ ├── app │ │ ├── BUCK │ │ ├── build.gradle │ │ ├── proguard-rules.pro │ │ └── src │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── calendarsexample │ │ │ │ ├── MainActivity.java │ │ │ │ └── MainApplication.java │ │ │ └── res │ │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ │ └── values │ │ │ ├── strings.xml │ │ │ └── styles.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── keystores │ │ ├── BUCK │ │ └── debug.keystore.properties │ └── settings.gradle ├── app.json ├── index.android.js ├── index.ios.js ├── ios │ ├── CalendarsExample-tvOS │ │ └── Info.plist │ ├── CalendarsExample-tvOSTests │ │ └── Info.plist │ ├── CalendarsExample.xcodeproj │ │ ├── project.pbxproj │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ ├── CalendarsExample-tvOS.xcscheme │ │ │ └── CalendarsExample.xcscheme │ ├── CalendarsExample │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Base.lproj │ │ │ └── LaunchScreen.xib │ │ ├── Images.xcassets │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ ├── Info.plist │ │ └── main.m │ └── CalendarsExampleTests │ │ ├── CalendarsExampleTests.m │ │ └── Info.plist ├── package.json └── src │ ├── app.js │ └── screens │ ├── agenda.js │ ├── calendars.js │ ├── calendarsList.js │ ├── horizontalCalendarList.js │ ├── index.js │ └── menu.js ├── package.json ├── pom.xml ├── scripts └── release.js ├── spec ├── runner.js └── support │ └── jasmine.json └── src ├── agenda ├── img │ └── knob@2x.png ├── index.js ├── platform-style.ios.js ├── platform-style.js ├── reservation-list │ ├── index.js │ ├── reservation.js │ └── style.js └── style.js ├── calendar-list ├── index.js ├── item.js └── style.js ├── calendar ├── day │ ├── basic │ │ ├── index.js │ │ └── style.js │ ├── custom │ │ ├── index.js │ │ └── style.js │ ├── multi-dot │ │ ├── index.js │ │ └── style.js │ ├── multi-period │ │ ├── index.js │ │ └── style.js │ └── period │ │ ├── index.js │ │ └── style.js ├── header │ ├── index.js │ └── style.js ├── img │ ├── next.png │ ├── next@1.5x.android.png │ ├── next@2x.android.png │ ├── next@2x.ios.png │ ├── next@3x.android.png │ ├── next@4x.android.png │ ├── previous.png │ ├── previous@1.5x.android.png │ ├── previous@2x.android.png │ ├── previous@2x.ios.png │ ├── previous@3x.android.png │ └── previous@4x.android.png ├── index.js ├── style.js └── updater.js ├── component-updater.js ├── component-updater.spec.js ├── dateutils.js ├── dateutils.spec.js ├── index.js ├── input.js ├── interface.js ├── interface.spec.js ├── style.js └── testIDs.js /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "es6": true, 4 | "node": true 5 | }, 6 | "globals": { 7 | "expect": true, 8 | "it": true, 9 | "describe": true, 10 | }, 11 | "extends": "eslint:recommended", 12 | "parser": "babel-eslint", 13 | "parserOptions": { 14 | "ecmaFeatures": { 15 | "experimentalObjectRestSpread": true, 16 | "jsx": true 17 | }, 18 | "sourceType": "module" 19 | }, 20 | "plugins": [ 21 | "react" 22 | ], 23 | "rules": { 24 | "no-unused-vars": 2, 25 | "react/jsx-uses-vars": 2, 26 | "react/jsx-uses-react": 2, 27 | "indent": [ 28 | "error", 29 | 2 30 | ], 31 | "linebreak-style": [ 32 | "error", 33 | "unix" 34 | ], 35 | "quotes": [ 36 | "error", 37 | "single" 38 | ], 39 | "semi": [ 40 | "error", 41 | "always" 42 | ] 43 | } 44 | }; 45 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | npm-debug.log 4 | .idea 5 | yarn.lock 6 | .vscode 7 | package-lock.json 8 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea 3 | src/**/*.spec.js 4 | example/ 5 | demo/ 6 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 6.9 2 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Please make our job easier by filling this template out to completion. If you're requesting a feature instead of reporting a bug, please feel free to skip the Environment and Reproducible Demo sections. 2 | 3 | ## Description 4 | 5 | 1-2 sentences describing the problem you're having or the feature you'd like to request 6 | 7 | ## Expected Behavior 8 | 9 | What action did you perform, and what did you expect to happen? 10 | 11 | ## Observed Behavior 12 | 13 | What actually happened when you performed the above actions? 14 | 15 | If there's an error message, please paste the *full terminal output and error message* in this code block: 16 | 17 | ``` 18 | Error text goes here! 19 | ``` 20 | 21 | ## Environment 22 | 23 | Please run these commands in the project folder and fill in their results: 24 | 25 | * `npm ls react-native-calendars`: 26 | * `npm ls react-native`: 27 | 28 | Also specify: 29 | 30 | 1. Phone/emulator/simulator & version: 31 | 32 | ## Reproducible Demo 33 | 34 | Please provide a minimized reproducible demonstration of the problem you're reporting. 35 | 36 | Issues that come with minimal repro's are resolved much more quickly than issues where a maintainer has to reproduce themselves. 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Wix.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React Native Toggle Calendar 2 | 3 | Horizontal as well as Grid calendar built on top of [react-native-calendars](https://github.com/wix/react-native-calendars) 4 | 5 | ### Demo 6 | 7 | 8 | 9 | ### What's special 10 | 11 | `react-native-calendars` has no support for custom header and horizontal scrollable calendar. 12 | This package provides these features along with some other properties like showing loader inside calendar. 13 | 14 | ### Usage 15 | 16 | 1. Install this library `yarn add react-native-toggle-calendar` 17 | 2. Use in your component like- 18 | 19 | ``` 20 | import { Calendar } from 'react-native-toggle-calendar'; 21 | 22 | 41 | ``` 42 | 43 | 44 | ### Available props 45 | 46 | All the props of https://github.com/wix/react-native-calendars are supported. Newly added ones are- 47 | 48 | ``` 49 | // Provide custom calendar header rendering component 50 | calendarHeaderComponent: PropTypes.any, 51 | // data which is passed to calendar header, useful only when implementing custom calendar header 52 | headerData: PropTypes.object, 53 | // Handler which gets executed when press list icon. It will set calendar to horizontal 54 | onPressListView: PropTypes.func, 55 | // Handler which gets executed when press grid icon. It will set calendar to grid 56 | onPressGridView: PropTypes.func, 57 | // to show horizontal calendar with scroll 58 | horizontal: PropTypes.bool, 59 | // to automatically scroll horizontal calendar to keep selected date in view 60 | autoHorizontalScroll: PropTypes.bool, 61 | // how many past days to be shown, if this is set - autoHorizontalScroll will not work 62 | showPastDatesInHorizontal: PropTypes.number, 63 | // offset to decide when to trigger onPressArrowRight in horizontal calendar, 64 | // 0 means when rightmost day is reached, undefined means no auto onPressArrowRight triggering 65 | horizontalEndReachedThreshold: PropTypes.number, 66 | // offset to decide when to trigger onPressArrowLeft in horizontal calendar, 67 | // 0 means when leftmost day is reached, undefined means no auto onPressArrowLeft triggering 68 | horizontalStartReachedThreshold: PropTypes.number, 69 | // to show a loader 70 | loading: PropTypes.bool, 71 | // provide a custom loader component 72 | LoaderComponent: PropTypes.any 73 | ``` 74 | 75 | ### Sample Calendar Day and Header Components- 76 | 77 | Check this gist: https://gist.github.com/varunon9/e204479219a55d86c4d8a985bae4e7f1 78 | 79 | ### Code changes from original package 80 | 81 | Check this PR: https://github.com/varunon9/react-native-toggle-calendar/pull/1 82 | 83 | Blog: https://medium.com/@varunon9/how-i-built-horizontal-as-well-as-grid-calendar-in-react-native-using-react-native-calendars-eb7a2edcc5db -------------------------------------------------------------------------------- /ToggleCalendar/.buckconfig: -------------------------------------------------------------------------------- 1 | 2 | [android] 3 | target = Google Inc.:Google APIs:23 4 | 5 | [maven_repositories] 6 | central = https://repo1.maven.org/maven2 7 | -------------------------------------------------------------------------------- /ToggleCalendar/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: '@react-native-community', 4 | }; 5 | -------------------------------------------------------------------------------- /ToggleCalendar/.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | ; We fork some components by platform 3 | .*/*[.]android.js 4 | 5 | ; Ignore "BUCK" generated dirs 6 | /\.buckd/ 7 | 8 | ; Ignore polyfills 9 | node_modules/react-native/Libraries/polyfills/.* 10 | 11 | ; These should not be required directly 12 | ; require from fbjs/lib instead: require('fbjs/lib/warning') 13 | node_modules/warning/.* 14 | 15 | ; Flow doesn't support platforms 16 | .*/Libraries/Utilities/LoadingView.js 17 | 18 | [untyped] 19 | .*/node_modules/@react-native-community/cli/.*/.* 20 | 21 | [include] 22 | 23 | [libs] 24 | node_modules/react-native/Libraries/react-native/react-native-interface.js 25 | node_modules/react-native/flow/ 26 | 27 | [options] 28 | emoji=true 29 | 30 | esproposal.optional_chaining=enable 31 | esproposal.nullish_coalescing=enable 32 | 33 | module.file_ext=.js 34 | module.file_ext=.json 35 | module.file_ext=.ios.js 36 | 37 | munge_underscores=true 38 | 39 | module.name_mapper='^react-native$' -> '/node_modules/react-native/Libraries/react-native/react-native-implementation' 40 | module.name_mapper='^react-native/\(.*\)$' -> '/node_modules/react-native/\1' 41 | module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> '/node_modules/react-native/Libraries/Image/RelativeImageStub' 42 | 43 | suppress_type=$FlowIssue 44 | suppress_type=$FlowFixMe 45 | suppress_type=$FlowFixMeProps 46 | suppress_type=$FlowFixMeState 47 | 48 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\) 49 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\)?:? #[0-9]+ 50 | suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError 51 | 52 | [lints] 53 | sketchy-null-number=warn 54 | sketchy-null-mixed=warn 55 | sketchy-number=warn 56 | untyped-type-import=warn 57 | nonstrict-import=warn 58 | deprecated-type=warn 59 | unsafe-getters-setters=warn 60 | inexact-spread=warn 61 | unnecessary-invariant=warn 62 | signature-verification-failure=warn 63 | deprecated-utility=error 64 | 65 | [strict] 66 | deprecated-type 67 | nonstrict-import 68 | sketchy-null 69 | unclear-type 70 | unsafe-getters-setters 71 | untyped-import 72 | untyped-type-import 73 | 74 | [version] 75 | ^0.105.0 76 | -------------------------------------------------------------------------------- /ToggleCalendar/.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | -------------------------------------------------------------------------------- /ToggleCalendar/.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 | project.xcworkspace 24 | 25 | # Android/IntelliJ 26 | # 27 | build/ 28 | .idea 29 | .gradle 30 | local.properties 31 | *.iml 32 | 33 | # node.js 34 | # 35 | node_modules/ 36 | npm-debug.log 37 | yarn-error.log 38 | 39 | # BUCK 40 | buck-out/ 41 | \.buckd/ 42 | *.keystore 43 | !debug.keystore 44 | 45 | # fastlane 46 | # 47 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 48 | # screenshots whenever they are needed. 49 | # For more information about the recommended setup visit: 50 | # https://docs.fastlane.tools/best-practices/source-control/ 51 | 52 | */fastlane/report.xml 53 | */fastlane/Preview.html 54 | */fastlane/screenshots 55 | 56 | # Bundle artifact 57 | *.jsbundle 58 | 59 | # CocoaPods 60 | /ios/Pods/ 61 | -------------------------------------------------------------------------------- /ToggleCalendar/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | bracketSpacing: false, 3 | jsxBracketSameLine: true, 4 | singleQuote: true, 5 | trailingComma: 'all', 6 | }; 7 | -------------------------------------------------------------------------------- /ToggleCalendar/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /ToggleCalendar/__tests__/App-test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import 'react-native'; 6 | import React from 'react'; 7 | import App from '../App'; 8 | 9 | // Note: test renderer must be required after react-native. 10 | import renderer from 'react-test-renderer'; 11 | 12 | it('renders correctly', () => { 13 | renderer.create(); 14 | }); 15 | -------------------------------------------------------------------------------- /ToggleCalendar/android/app/BUCK: -------------------------------------------------------------------------------- 1 | # To learn about Buck see [Docs](https://buckbuild.com/). 2 | # To run your application with Buck: 3 | # - install Buck 4 | # - `npm start` - to start the packager 5 | # - `cd android` 6 | # - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"` 7 | # - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck 8 | # - `buck install -r android/app` - compile, install and run application 9 | # 10 | 11 | load(":build_defs.bzl", "create_aar_targets", "create_jar_targets") 12 | 13 | lib_deps = [] 14 | 15 | create_aar_targets(glob(["libs/*.aar"])) 16 | 17 | create_jar_targets(glob(["libs/*.jar"])) 18 | 19 | android_library( 20 | name = "all-libs", 21 | exported_deps = lib_deps, 22 | ) 23 | 24 | android_library( 25 | name = "app-code", 26 | srcs = glob([ 27 | "src/main/java/**/*.java", 28 | ]), 29 | deps = [ 30 | ":all-libs", 31 | ":build_config", 32 | ":res", 33 | ], 34 | ) 35 | 36 | android_build_config( 37 | name = "build_config", 38 | package = "com.togglecalendar", 39 | ) 40 | 41 | android_resource( 42 | name = "res", 43 | package = "com.togglecalendar", 44 | res = "src/main/res", 45 | ) 46 | 47 | android_binary( 48 | name = "app", 49 | keystore = "//android/keystores:debug", 50 | manifest = "src/main/AndroidManifest.xml", 51 | package_type = "debug", 52 | deps = [ 53 | ":app-code", 54 | ], 55 | ) 56 | -------------------------------------------------------------------------------- /ToggleCalendar/android/app/build_defs.bzl: -------------------------------------------------------------------------------- 1 | """Helper definitions to glob .aar and .jar targets""" 2 | 3 | def create_aar_targets(aarfiles): 4 | for aarfile in aarfiles: 5 | name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")] 6 | lib_deps.append(":" + name) 7 | android_prebuilt_aar( 8 | name = name, 9 | aar = aarfile, 10 | ) 11 | 12 | def create_jar_targets(jarfiles): 13 | for jarfile in jarfiles: 14 | name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")] 15 | lib_deps.append(":" + name) 16 | prebuilt_jar( 17 | name = name, 18 | binary_jar = jarfile, 19 | ) 20 | -------------------------------------------------------------------------------- /ToggleCalendar/android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/ToggleCalendar/android/app/debug.keystore -------------------------------------------------------------------------------- /ToggleCalendar/android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | -------------------------------------------------------------------------------- /ToggleCalendar/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ToggleCalendar/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 13 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ToggleCalendar/android/app/src/main/java/com/togglecalendar/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.togglecalendar; 2 | 3 | import com.facebook.react.ReactActivity; 4 | 5 | public class MainActivity extends ReactActivity { 6 | 7 | /** 8 | * Returns the name of the main component registered from JavaScript. This is used to schedule 9 | * rendering of the component. 10 | */ 11 | @Override 12 | protected String getMainComponentName() { 13 | return "ToggleCalendar"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ToggleCalendar/android/app/src/main/java/com/togglecalendar/MainApplication.java: -------------------------------------------------------------------------------- 1 | package com.togglecalendar; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | import com.facebook.react.PackageList; 6 | import com.facebook.react.ReactApplication; 7 | import com.facebook.react.ReactNativeHost; 8 | import com.facebook.react.ReactPackage; 9 | import com.facebook.soloader.SoLoader; 10 | import java.lang.reflect.InvocationTargetException; 11 | import java.util.List; 12 | 13 | public class MainApplication extends Application implements ReactApplication { 14 | 15 | private final ReactNativeHost mReactNativeHost = 16 | new ReactNativeHost(this) { 17 | @Override 18 | public boolean getUseDeveloperSupport() { 19 | return BuildConfig.DEBUG; 20 | } 21 | 22 | @Override 23 | protected List getPackages() { 24 | @SuppressWarnings("UnnecessaryLocalVariable") 25 | List packages = new PackageList(this).getPackages(); 26 | // Packages that cannot be autolinked yet can be added manually here, for example: 27 | // packages.add(new MyReactNativePackage()); 28 | return packages; 29 | } 30 | 31 | @Override 32 | protected String getJSMainModuleName() { 33 | return "index"; 34 | } 35 | }; 36 | 37 | @Override 38 | public ReactNativeHost getReactNativeHost() { 39 | return mReactNativeHost; 40 | } 41 | 42 | @Override 43 | public void onCreate() { 44 | super.onCreate(); 45 | SoLoader.init(this, /* native exopackage */ false); 46 | initializeFlipper(this); // Remove this line if you don't want Flipper enabled 47 | } 48 | 49 | /** 50 | * Loads Flipper in React Native templates. 51 | * 52 | * @param context 53 | */ 54 | private static void initializeFlipper(Context context) { 55 | if (BuildConfig.DEBUG) { 56 | try { 57 | /* 58 | We use reflection here to pick up the class that initializes Flipper, 59 | since Flipper library is not available in release mode 60 | */ 61 | Class aClass = Class.forName("com.facebook.flipper.ReactNativeFlipper"); 62 | aClass.getMethod("initializeFlipper", Context.class).invoke(null, context); 63 | } catch (ClassNotFoundException e) { 64 | e.printStackTrace(); 65 | } catch (NoSuchMethodException e) { 66 | e.printStackTrace(); 67 | } catch (IllegalAccessException e) { 68 | e.printStackTrace(); 69 | } catch (InvocationTargetException e) { 70 | e.printStackTrace(); 71 | } 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /ToggleCalendar/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/ToggleCalendar/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /ToggleCalendar/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/ToggleCalendar/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /ToggleCalendar/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/ToggleCalendar/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /ToggleCalendar/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/ToggleCalendar/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /ToggleCalendar/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/ToggleCalendar/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /ToggleCalendar/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/ToggleCalendar/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /ToggleCalendar/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/ToggleCalendar/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /ToggleCalendar/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/ToggleCalendar/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /ToggleCalendar/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/ToggleCalendar/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /ToggleCalendar/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/ToggleCalendar/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /ToggleCalendar/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | ToggleCalendar 3 | 4 | -------------------------------------------------------------------------------- /ToggleCalendar/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /ToggleCalendar/android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext { 5 | buildToolsVersion = "28.0.3" 6 | minSdkVersion = 16 7 | compileSdkVersion = 28 8 | targetSdkVersion = 28 9 | } 10 | repositories { 11 | google() 12 | jcenter() 13 | } 14 | dependencies { 15 | classpath("com.android.tools.build:gradle:3.4.2") 16 | 17 | // NOTE: Do not place your application dependencies here; they belong 18 | // in the individual module build.gradle files 19 | } 20 | } 21 | 22 | allprojects { 23 | repositories { 24 | mavenLocal() 25 | maven { 26 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 27 | url("$rootDir/../node_modules/react-native/android") 28 | } 29 | maven { 30 | // Android JSC is installed from npm 31 | url("$rootDir/../node_modules/jsc-android/dist") 32 | } 33 | 34 | google() 35 | jcenter() 36 | maven { url 'https://jitpack.io' } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /ToggleCalendar/android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | android.useAndroidX=true 21 | android.enableJetifier=true 22 | -------------------------------------------------------------------------------- /ToggleCalendar/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/ToggleCalendar/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /ToggleCalendar/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.5-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /ToggleCalendar/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem http://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 33 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 34 | 35 | @rem Find java.exe 36 | if defined JAVA_HOME goto findJavaFromJavaHome 37 | 38 | set JAVA_EXE=java.exe 39 | %JAVA_EXE% -version >NUL 2>&1 40 | if "%ERRORLEVEL%" == "0" goto init 41 | 42 | echo. 43 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 44 | echo. 45 | echo Please set the JAVA_HOME variable in your environment to match the 46 | echo location of your Java installation. 47 | 48 | goto fail 49 | 50 | :findJavaFromJavaHome 51 | set JAVA_HOME=%JAVA_HOME:"=% 52 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 53 | 54 | if exist "%JAVA_EXE%" goto init 55 | 56 | echo. 57 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 58 | echo. 59 | echo Please set the JAVA_HOME variable in your environment to match the 60 | echo location of your Java installation. 61 | 62 | goto fail 63 | 64 | :init 65 | @rem Get command-line arguments, handling Windows variants 66 | 67 | if not "%OS%" == "Windows_NT" goto win9xME_args 68 | 69 | :win9xME_args 70 | @rem Slurp the command line arguments. 71 | set CMD_LINE_ARGS= 72 | set _SKIP=2 73 | 74 | :win9xME_args_slurp 75 | if "x%~1" == "x" goto execute 76 | 77 | set CMD_LINE_ARGS=%* 78 | 79 | :execute 80 | @rem Setup the command line 81 | 82 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 83 | 84 | @rem Execute Gradle 85 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 86 | 87 | :end 88 | @rem End local scope for the variables with windows NT shell 89 | if "%ERRORLEVEL%"=="0" goto mainEnd 90 | 91 | :fail 92 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 93 | rem the _cmd.exe /c_ return code! 94 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 95 | exit /b 1 96 | 97 | :mainEnd 98 | if "%OS%"=="Windows_NT" endlocal 99 | 100 | :omega 101 | -------------------------------------------------------------------------------- /ToggleCalendar/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'ToggleCalendar' 2 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) 3 | include ':app' 4 | -------------------------------------------------------------------------------- /ToggleCalendar/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ToggleCalendar", 3 | "displayName": "ToggleCalendar" 4 | } -------------------------------------------------------------------------------- /ToggleCalendar/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:metro-react-native-babel-preset'], 3 | }; 4 | -------------------------------------------------------------------------------- /ToggleCalendar/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import {AppRegistry} from 'react-native'; 6 | import App from './src/App'; 7 | import {name as appName} from './app.json'; 8 | 9 | AppRegistry.registerComponent(appName, () => App); 10 | -------------------------------------------------------------------------------- /ToggleCalendar/ios/Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '9.0' 2 | require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' 3 | 4 | target 'ToggleCalendar' do 5 | # Pods for ToggleCalendar 6 | pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector" 7 | pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec" 8 | pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired" 9 | pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety" 10 | pod 'React', :path => '../node_modules/react-native/' 11 | pod 'React-Core', :path => '../node_modules/react-native/' 12 | pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules' 13 | pod 'React-Core/DevSupport', :path => '../node_modules/react-native/' 14 | pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS' 15 | pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation' 16 | pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob' 17 | pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image' 18 | pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS' 19 | pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network' 20 | pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings' 21 | pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text' 22 | pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration' 23 | pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/' 24 | 25 | pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact' 26 | pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi' 27 | pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor' 28 | pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector' 29 | pod 'ReactCommon/jscallinvoker', :path => "../node_modules/react-native/ReactCommon" 30 | pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon" 31 | pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga' 32 | 33 | pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec' 34 | pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec' 35 | pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec' 36 | 37 | target 'ToggleCalendarTests' do 38 | inherit! :search_paths 39 | # Pods for testing 40 | end 41 | 42 | use_native_modules! 43 | end 44 | 45 | target 'ToggleCalendar-tvOS' do 46 | # Pods for ToggleCalendar-tvOS 47 | 48 | target 'ToggleCalendar-tvOSTests' do 49 | inherit! :search_paths 50 | # Pods for testing 51 | end 52 | 53 | end 54 | -------------------------------------------------------------------------------- /ToggleCalendar/ios/ToggleCalendar-tvOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | NSAppTransportSecurity 26 | 27 | NSExceptionDomains 28 | 29 | localhost 30 | 31 | NSExceptionAllowsInsecureHTTPLoads 32 | 33 | 34 | 35 | 36 | NSLocationWhenInUseUsageDescription 37 | 38 | UILaunchStoryboardName 39 | LaunchScreen 40 | UIRequiredDeviceCapabilities 41 | 42 | armv7 43 | 44 | UISupportedInterfaceOrientations 45 | 46 | UIInterfaceOrientationPortrait 47 | UIInterfaceOrientationLandscapeLeft 48 | UIInterfaceOrientationLandscapeRight 49 | 50 | UIViewControllerBasedStatusBarAppearance 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /ToggleCalendar/ios/ToggleCalendar-tvOSTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /ToggleCalendar/ios/ToggleCalendar.xcodeproj/xcshareddata/xcschemes/ToggleCalendar-tvOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 43 | 49 | 50 | 51 | 52 | 53 | 58 | 59 | 61 | 67 | 68 | 69 | 70 | 71 | 77 | 78 | 79 | 80 | 81 | 82 | 92 | 94 | 100 | 101 | 102 | 103 | 104 | 105 | 111 | 113 | 119 | 120 | 121 | 122 | 124 | 125 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /ToggleCalendar/ios/ToggleCalendar.xcodeproj/xcshareddata/xcschemes/ToggleCalendar.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 43 | 49 | 50 | 51 | 52 | 53 | 58 | 59 | 61 | 67 | 68 | 69 | 70 | 71 | 77 | 78 | 79 | 80 | 81 | 82 | 92 | 94 | 100 | 101 | 102 | 103 | 104 | 105 | 111 | 113 | 119 | 120 | 121 | 122 | 124 | 125 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /ToggleCalendar/ios/ToggleCalendar/AppDelegate.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #import 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (nonatomic, strong) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ToggleCalendar/ios/ToggleCalendar/AppDelegate.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #import "AppDelegate.h" 9 | 10 | #import 11 | #import 12 | #import 13 | 14 | @implementation AppDelegate 15 | 16 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 17 | { 18 | RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; 19 | RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge 20 | moduleName:@"ToggleCalendar" 21 | initialProperties:nil]; 22 | 23 | rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1]; 24 | 25 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 26 | UIViewController *rootViewController = [UIViewController new]; 27 | rootViewController.view = rootView; 28 | self.window.rootViewController = rootViewController; 29 | [self.window makeKeyAndVisible]; 30 | return YES; 31 | } 32 | 33 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge 34 | { 35 | #if DEBUG 36 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; 37 | #else 38 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; 39 | #endif 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /ToggleCalendar/ios/ToggleCalendar/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /ToggleCalendar/ios/ToggleCalendar/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /ToggleCalendar/ios/ToggleCalendar/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ToggleCalendar/ios/ToggleCalendar/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ToggleCalendar 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSRequiresIPhoneOS 26 | 27 | NSAppTransportSecurity 28 | 29 | NSAllowsArbitraryLoads 30 | 31 | NSExceptionDomains 32 | 33 | localhost 34 | 35 | NSExceptionAllowsInsecureHTTPLoads 36 | 37 | 38 | 39 | 40 | NSLocationWhenInUseUsageDescription 41 | 42 | UILaunchStoryboardName 43 | LaunchScreen 44 | UIRequiredDeviceCapabilities 45 | 46 | armv7 47 | 48 | UISupportedInterfaceOrientations 49 | 50 | UIInterfaceOrientationPortrait 51 | UIInterfaceOrientationLandscapeLeft 52 | UIInterfaceOrientationLandscapeRight 53 | 54 | UIViewControllerBasedStatusBarAppearance 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /ToggleCalendar/ios/ToggleCalendar/main.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #import 9 | 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ToggleCalendar/ios/ToggleCalendarTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /ToggleCalendar/ios/ToggleCalendarTests/ToggleCalendarTests.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #import 9 | #import 10 | 11 | #import 12 | #import 13 | 14 | #define TIMEOUT_SECONDS 600 15 | #define TEXT_TO_LOOK_FOR @"Welcome to React" 16 | 17 | @interface ToggleCalendarTests : XCTestCase 18 | 19 | @end 20 | 21 | @implementation ToggleCalendarTests 22 | 23 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test 24 | { 25 | if (test(view)) { 26 | return YES; 27 | } 28 | for (UIView *subview in [view subviews]) { 29 | if ([self findSubviewInView:subview matching:test]) { 30 | return YES; 31 | } 32 | } 33 | return NO; 34 | } 35 | 36 | - (void)testRendersWelcomeScreen 37 | { 38 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; 39 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; 40 | BOOL foundElement = NO; 41 | 42 | __block NSString *redboxError = nil; 43 | #ifdef DEBUG 44 | RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { 45 | if (level >= RCTLogLevelError) { 46 | redboxError = message; 47 | } 48 | }); 49 | #endif 50 | 51 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { 52 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 53 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 54 | 55 | foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) { 56 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { 57 | return YES; 58 | } 59 | return NO; 60 | }]; 61 | } 62 | 63 | #ifdef DEBUG 64 | RCTSetLogFunction(RCTDefaultLogFunction); 65 | #endif 66 | 67 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); 68 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); 69 | } 70 | 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /ToggleCalendar/metro.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Metro configuration for React Native 3 | * https://github.com/facebook/react-native 4 | * 5 | * @format 6 | */ 7 | 8 | module.exports = { 9 | transformer: { 10 | getTransformOptions: async () => ({ 11 | transform: { 12 | experimentalImportSupport: false, 13 | inlineRequires: false, 14 | }, 15 | }), 16 | }, 17 | }; 18 | -------------------------------------------------------------------------------- /ToggleCalendar/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ToggleCalendar", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "android": "react-native run-android", 7 | "ios": "react-native run-ios", 8 | "start": "react-native start", 9 | "test": "jest" 10 | }, 11 | "dependencies": { 12 | "moment": "^2.24.0", 13 | "react": "16.8.1", 14 | "react-native": "0.61.1", 15 | "react-native-toggle-calendar": "^1.0.2" 16 | }, 17 | "devDependencies": { 18 | "@babel/core": "^7.5.0", 19 | "@babel/runtime": "^7.5.0", 20 | "@react-native-community/eslint-config": "^0.0.3", 21 | "babel-jest": "^24.1.0", 22 | "jest": "^24.1.0", 23 | "metro-react-native-babel-preset": "^0.51.1", 24 | "react-test-renderer": "16.8.1" 25 | }, 26 | "jest": { 27 | "preset": "react-native" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ToggleCalendar/src/App.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Sample React Native App 3 | * https://github.com/facebook/react-native 4 | * 5 | * @format 6 | * @flow 7 | */ 8 | 9 | import React from 'react'; 10 | import { 11 | SafeAreaView, 12 | StyleSheet, 13 | ScrollView, 14 | View, 15 | Text, 16 | StatusBar, 17 | } from 'react-native'; 18 | import { Calendar } from 'react-native-toggle-calendar'; 19 | import moment from 'moment'; 20 | 21 | import CalendarDayComponent from './components/CalendarDayComponent'; 22 | import CalendarHeaderComponent from './components/CalendarHeaderComponent'; 23 | import CalendarFooterComponent from './components/CalendarFooterComponent'; 24 | 25 | let selectedCalendarDate = moment(); 26 | const minimumDate = moment().add(-1, 'day'); // one day before for midnight check-in usecase 27 | const currentDate = moment(); 28 | 29 | class App extends React.Component { 30 | 31 | constructor(props) { 32 | super(props); 33 | 34 | this.state = { 35 | selectedCalendarDateString: selectedCalendarDate.format('YYYY-MM-DD'), 36 | selectedCalendarMonthString: selectedCalendarDate.format('YYYY-MM-DD'), 37 | calendarHeaderData: {}, 38 | calendarMarkedDates: { 39 | '2019-09-01': { 40 | fullySoldOut: false, 41 | partiallySoldOut: false, 42 | fullyBlocked: false, 43 | partiallyBlocked: true, 44 | inventory: 14, 45 | highDemand: false, 46 | selected: false 47 | }, 48 | '2019-10-01': { 49 | fullySoldOut: false, 50 | partiallySoldOut: false, 51 | fullyBlocked: false, 52 | partiallyBlocked: true, 53 | inventory: 14, 54 | highDemand: true, 55 | selected: false 56 | }, 57 | '2019-11-01': { 58 | fullySoldOut: false, 59 | partiallySoldOut: false, 60 | fullyBlocked: false, 61 | partiallyBlocked: true, 62 | inventory: 14, 63 | highDemand: false, 64 | selected: false 65 | } 66 | }, 67 | horizontal: true, 68 | ratesInventoryDataArray: [], 69 | saveButtonClicked: false, 70 | calendarLoading: true 71 | }; 72 | 73 | this.onPressArrowLeft = this.onPressArrowLeft.bind(this); 74 | this.onPressArrowRight = this.onPressArrowRight.bind(this); 75 | this.onPressListView = this.onPressListView.bind(this); 76 | this.onPressGridView = this.onPressGridView.bind(this); 77 | } 78 | 79 | updateSelectedCalendarMonth(selectedCalendarMonthString) { 80 | this.setState({ 81 | selectedCalendarMonthString, 82 | calendarLoading: true 83 | }); 84 | } 85 | 86 | onDayPress(date) { 87 | selectedCalendarDate = moment(date.dateString); 88 | const selectedCalendarDateString = selectedCalendarDate.format( 89 | 'YYYY-MM-DD' 90 | ); 91 | this.setState({ 92 | ratesInventoryDataArray: [], // reset inventory data 93 | selectedCalendarDateString, 94 | selectedCalendarMonthString: selectedCalendarDateString 95 | }); 96 | /*this.fetchDemandData(selectedCalendarDateString); 97 | this.fetchMultiDaysInventoryData(selectedCalendarDateString); 98 | this.fetchRatesAndInventoryData(selectedCalendarDateString);*/ 99 | } 100 | 101 | onPressArrowLeft(currentMonth, addMonthCallback) { 102 | const monthStartDate = moment(currentMonth.getTime()).startOf('month'); 103 | 104 | // don't go back for past months 105 | if (monthStartDate > currentDate) { 106 | addMonthCallback(-1); 107 | const selectedCalendarMonthString = moment(currentMonth.getTime()) 108 | .add(-1, 'month') 109 | .format('YYYY-MM-DD'); 110 | this.updateSelectedCalendarMonth(selectedCalendarMonthString); 111 | } 112 | } 113 | 114 | onPressArrowRight(currentMonth, addMonthCallback) { 115 | addMonthCallback(1); 116 | const selectedCalendarMonthString = moment(currentMonth.getTime()) 117 | .add(1, 'month') 118 | .format('YYYY-MM-DD'); 119 | this.updateSelectedCalendarMonth(selectedCalendarMonthString); 120 | } 121 | 122 | onPressListView() { 123 | this.setState({ horizontal: true }); 124 | } 125 | 126 | onPressGridView() { 127 | this.setState({ horizontal: false }); 128 | } 129 | 130 | render() { 131 | return ( 132 | <> 133 | 134 | 135 | 154 | 157 | 158 | 159 | ); 160 | } 161 | }; 162 | 163 | const styles = StyleSheet.create({ 164 | scrollView: { 165 | } 166 | }); 167 | 168 | export default App; 169 | -------------------------------------------------------------------------------- /ToggleCalendar/src/components/CalendarDayComponent.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { View, Text, StyleSheet, TouchableOpacity, Image } from 'react-native'; 3 | import PropTypes from 'prop-types'; 4 | 5 | const weekDaysNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; 6 | 7 | class InventoryCount extends React.PureComponent { 8 | getFooterTextStyle() { 9 | const { marking = {}, state } = this.props; 10 | const style = { 11 | color: '#c1c2c1' 12 | }; 13 | 14 | if (marking.inventory > 0 && state !== 'disabled') { 15 | style.color = '#4caf50'; 16 | } 17 | return style; 18 | } 19 | 20 | getInventoryCount() { 21 | const { marking = {}, state } = this.props; 22 | if (typeof marking === 'object' && state !== 'disabled') { 23 | if (marking.inventory >= 0) { 24 | return marking.inventory; 25 | } 26 | } 27 | if (state === 'disabled') { 28 | return ''; 29 | } else { 30 | return 'NA'; 31 | } 32 | } 33 | 34 | render() { 35 | return ( 36 | 37 | 38 | {this.getInventoryCount()} 39 | 40 | 41 | ); 42 | } 43 | } 44 | 45 | class CalendarDayComponent extends React.PureComponent { 46 | constructor(props) { 47 | super(props); 48 | this.onDayPress = this.onDayPress.bind(this); 49 | } 50 | 51 | getContentStyle() { 52 | const { state, marking = {} } = this.props; 53 | const style = { 54 | content: {}, 55 | text: { 56 | color: '#181c26' 57 | } 58 | }; 59 | 60 | if (state === 'disabled') { 61 | style.text.color = '#c1c2c1'; 62 | } else { 63 | if (marking.partiallyBlocked) { 64 | style.content.borderColor = '#c1c2c1'; 65 | style.content.borderRadius = 50; 66 | style.content.borderWidth = 1; 67 | } else if (marking.partiallySoldOut) { 68 | style.content.borderColor = '#e35052'; 69 | style.content.borderRadius = 50; 70 | style.content.borderWidth = 1; 71 | } 72 | 73 | if (marking.selected) { 74 | style.text.color = '#fff'; 75 | style.content.backgroundColor = '#216bc9'; 76 | style.content.borderRadius = 50; 77 | } else if (marking.fullyBlocked) { 78 | style.text.color = '#fff'; 79 | style.content.backgroundColor = '#c1c2c1'; 80 | style.content.borderRadius = 50; 81 | } else if (marking.fullySoldOut) { 82 | style.text.color = '#fff'; 83 | style.content.backgroundColor = '#e35052'; 84 | style.content.borderRadius = 50; 85 | } 86 | } 87 | 88 | return style; 89 | } 90 | 91 | onDayPress() { 92 | this.props.onPress(this.props.date); 93 | } 94 | 95 | render() { 96 | const contentStyle = this.getContentStyle(); 97 | const highDemandImage = require('../images/high-demand.png'); 98 | 99 | return ( 100 | 101 | 102 | {this.props.horizontal ? ( 103 | 104 | {weekDaysNames[this.props.date.weekDay].toUpperCase()} 105 | 106 | ) : null} 107 | 108 | 112 | 113 | {String(this.props.children)} 114 | 115 | {this.props.marking.highDemand && this.props.state !== 'disabled' ? ( 116 | 117 | ) : null} 118 | 119 | 120 | 121 | ); 122 | } 123 | } 124 | 125 | class CalendarDayWrapper extends React.PureComponent { 126 | render() { 127 | return ; 128 | } 129 | } 130 | 131 | CalendarDayComponent.propTypes = { 132 | children: PropTypes.any, 133 | state: PropTypes.string, 134 | marking: PropTypes.any, 135 | horizontal: PropTypes.bool, 136 | date: PropTypes.object, 137 | onPress: PropTypes.func.isRequired, 138 | current: PropTypes.string, 139 | copilot: PropTypes.object 140 | }; 141 | 142 | const styles = StyleSheet.create({ 143 | container: { 144 | justifyContent: 'center', 145 | alignItems: 'center', 146 | marginLeft: 7, 147 | marginRight: 7 148 | }, 149 | weekName: { 150 | width: 32, 151 | textAlign: 'center', 152 | fontSize: 12, 153 | fontWeight: 'bold', 154 | color: '#7c7c7c' 155 | }, 156 | content: { 157 | width: 36, 158 | height: 36, 159 | justifyContent: 'center', 160 | alignItems: 'center' 161 | }, 162 | contentText: { 163 | fontSize: 20 164 | }, 165 | footer: { 166 | flexDirection: 'row' 167 | }, 168 | smallIcon: { 169 | width: 12, 170 | height: 12, 171 | position: 'absolute', 172 | top: -1, 173 | right: -1 174 | } 175 | }); 176 | 177 | export default CalendarDayWrapper; 178 | -------------------------------------------------------------------------------- /ToggleCalendar/src/components/CalendarFooterComponent.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { View, Text, StyleSheet, Image } from 'react-native'; 3 | import PropTypes from 'prop-types'; 4 | 5 | class CalendarFooterComponent extends React.PureComponent { 6 | constructor(props) { 7 | super(props); 8 | } 9 | 10 | render() { 11 | const highDemandImage = require('../images/high-demand.png'); 12 | 13 | return ( 14 | 15 | 16 | 17 | 18 | ROOMS SOLD OUT 19 | 20 | 21 | 22 | BLOCKED 23 | 24 | 25 | 26 | HIGH DEMAND 27 | 28 | 29 | 30 | {this.props.calendarDateString} 31 | 32 | 33 | ); 34 | } 35 | } 36 | 37 | CalendarFooterComponent.propTypes = { 38 | calendarDateString: PropTypes.string.isRequired 39 | }; 40 | 41 | const styles = StyleSheet.create({ 42 | container: { 43 | backgroundColor: '#eceef1', 44 | borderTopWidth: 1, 45 | borderTopColor: '#ccc', 46 | paddingLeft: 10, 47 | paddingRight: 10, 48 | paddingTop: 10 49 | }, 50 | header: { 51 | flexDirection: 'row', 52 | justifyContent: 'space-between' 53 | }, 54 | iconInfo: { 55 | flexDirection: 'row', 56 | marginRight: 10, 57 | alignItems: 'center' 58 | }, 59 | highDemandInfo: { 60 | marginRight: 0 61 | }, 62 | infoText: { 63 | fontSize: 12, 64 | color: '#2D3332', 65 | marginLeft: 6 66 | }, 67 | circle: { 68 | width: 12, 69 | height: 12, 70 | borderRadius: 50 71 | }, 72 | soldOutCircle: { 73 | backgroundColor: '#e35052' 74 | }, 75 | blockedCircle: { 76 | backgroundColor: '#c1c2c1' 77 | }, 78 | footer: { 79 | marginTop: 12, 80 | marginBottom: 10 81 | }, 82 | smallIcon: { 83 | width: 12, 84 | height: 12, 85 | marginLeft: 4 86 | }, 87 | footerText: { 88 | color: '#2D3332', 89 | fontWeight: 'bold', 90 | textAlign: 'center', 91 | fontSize: 17 92 | }, 93 | red: { 94 | color: '#e35052' 95 | } 96 | }); 97 | 98 | export default CalendarFooterComponent; 99 | -------------------------------------------------------------------------------- /ToggleCalendar/src/components/CalendarHeaderComponent.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { View, Text, StyleSheet, Image, TouchableOpacity } from 'react-native'; 3 | import PropTypes from 'prop-types'; 4 | import moment from 'moment'; 5 | 6 | const weekDaysNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; 7 | const now = moment(); 8 | 9 | class CalendarHeaderComponent extends React.PureComponent { 10 | constructor(props) { 11 | super(props); 12 | this.onPressArrowLeft = this.onPressArrowLeft.bind(this); 13 | this.onPressArrowRight = this.onPressArrowRight.bind(this); 14 | this.shouldLeftArrowBeDisabled = this.shouldLeftArrowBeDisabled.bind(this); 15 | } 16 | 17 | onPressArrowLeft() { 18 | this.props.onPressArrowLeft(this.props.month, this.props.addMonth); 19 | } 20 | 21 | onPressArrowRight() { 22 | this.props.onPressArrowRight(this.props.month, this.props.addMonth); 23 | } 24 | 25 | shouldLeftArrowBeDisabled() { 26 | const selectedDate = moment(this.props.month.getTime()); 27 | return selectedDate.isSame(now, 'month'); 28 | } 29 | 30 | render() { 31 | return ( 32 | 33 | 34 | 35 | {moment(this.props.month.getTime()).format('MMM, YYYY')} 36 | 37 | 43 | 47 | 51 | 52 | 53 | 57 | 61 | 62 | 63 | {!this.props.horizontal ? ( 64 | 73 | 77 | 78 | ) : null} 79 | {this.props.horizontal ? ( 80 | 89 | 93 | 94 | ) : null} 95 | 96 | {// not showing week day in case of horizontal calendar, this will be handled by day component 97 | this.props.horizontal ? null : ( 98 | 99 | {weekDaysNames.map((day, index) => ( 100 | 101 | {day.toUpperCase()} 102 | 103 | ))} 104 | 105 | )} 106 | 107 | ); 108 | } 109 | } 110 | 111 | CalendarHeaderComponent.propTypes = { 112 | headerData: PropTypes.object, 113 | horizontal: PropTypes.bool, 114 | onPressArrowRight: PropTypes.func.isRequired, 115 | onPressArrowLeft: PropTypes.func.isRequired, 116 | onPressListView: PropTypes.func.isRequired, 117 | onPressGridView: PropTypes.func.isRequired, 118 | addMonth: PropTypes.func, 119 | month: PropTypes.object 120 | }; 121 | 122 | const styles = StyleSheet.create({ 123 | header: { 124 | flexDirection: 'row', 125 | padding: 12, 126 | backgroundColor: '#eceef1' 127 | }, 128 | week: { 129 | marginTop: 7, 130 | flexDirection: 'row', 131 | justifyContent: 'space-around' 132 | }, 133 | weekName: { 134 | marginTop: 2, 135 | marginBottom: 7, 136 | width: 32, 137 | textAlign: 'center', 138 | fontSize: 12, 139 | fontWeight: 'bold', 140 | color: '#7c7c7c' 141 | }, 142 | dateText: { 143 | fontSize: 18 144 | }, 145 | iconContainer: { 146 | justifyContent: 'center', 147 | alignItems: 'center', 148 | marginLeft: 8, 149 | marginRight: 4, 150 | marginTop: -2 151 | }, 152 | leftIcon: { 153 | transform: [{ rotate: '180deg' }] 154 | }, 155 | icon: { 156 | width: 24, 157 | height: 24 158 | }, 159 | disabled: { 160 | opacity: 0.4 161 | } 162 | }); 163 | 164 | export default CalendarHeaderComponent; 165 | -------------------------------------------------------------------------------- /ToggleCalendar/src/images/arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/ToggleCalendar/src/images/arrow.png -------------------------------------------------------------------------------- /ToggleCalendar/src/images/grid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/ToggleCalendar/src/images/grid.png -------------------------------------------------------------------------------- /ToggleCalendar/src/images/high-demand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/ToggleCalendar/src/images/high-demand.png -------------------------------------------------------------------------------- /ToggleCalendar/src/images/list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/ToggleCalendar/src/images/list.png -------------------------------------------------------------------------------- /demo/agenda.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/demo/agenda.gif -------------------------------------------------------------------------------- /demo/calendar-list.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/demo/calendar-list.gif -------------------------------------------------------------------------------- /demo/calendar.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/demo/calendar.gif -------------------------------------------------------------------------------- /demo/custom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/demo/custom.png -------------------------------------------------------------------------------- /demo/horizontal-calendar-list.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/demo/horizontal-calendar-list.gif -------------------------------------------------------------------------------- /demo/loader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/demo/loader.png -------------------------------------------------------------------------------- /demo/marking1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/demo/marking1.png -------------------------------------------------------------------------------- /demo/marking2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/demo/marking2.png -------------------------------------------------------------------------------- /demo/marking3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/demo/marking3.png -------------------------------------------------------------------------------- /demo/marking4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/demo/marking4.png -------------------------------------------------------------------------------- /demo/marking5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/demo/marking5.png -------------------------------------------------------------------------------- /demo/marking6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/demo/marking6.png -------------------------------------------------------------------------------- /example/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "module:metro-react-native-babel-preset" 4 | ] 5 | } -------------------------------------------------------------------------------- /example/.buckconfig: -------------------------------------------------------------------------------- 1 | 2 | [android] 3 | target = Google Inc.:Google APIs:23 4 | 5 | [maven_repositories] 6 | central = https://repo1.maven.org/maven2 7 | -------------------------------------------------------------------------------- /example/.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | ; We fork some components by platform 3 | .*/*[.]android.js 4 | 5 | ; Ignore "BUCK" generated dirs 6 | /\.buckd/ 7 | 8 | ; Ignore unexpected extra "@providesModule" 9 | .*/node_modules/.*/node_modules/fbjs/.* 10 | 11 | ; Ignore duplicate module providers 12 | ; For RN Apps installed via npm, "Libraries" folder is inside 13 | ; "node_modules/react-native" but in the source repo it is in the root 14 | .*/Libraries/react-native/React.js 15 | .*/Libraries/react-native/ReactNative.js 16 | 17 | [include] 18 | 19 | [libs] 20 | node_modules/react-native/Libraries/react-native/react-native-interface.js 21 | node_modules/react-native/flow 22 | flow/ 23 | 24 | [options] 25 | emoji=true 26 | 27 | module.system=haste 28 | 29 | munge_underscores=true 30 | 31 | module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub' 32 | 33 | suppress_type=$FlowIssue 34 | suppress_type=$FlowFixMe 35 | suppress_type=$FixMe 36 | 37 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(4[0-9]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\) 38 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(4[0-9]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+ 39 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy 40 | suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError 41 | 42 | unsafe.enable_getters_and_setters=true 43 | 44 | [version] 45 | ^0.49.1 46 | -------------------------------------------------------------------------------- /example/.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | -------------------------------------------------------------------------------- /example/.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 | project.xcworkspace 24 | 25 | # Android/IntelliJ 26 | # 27 | build/ 28 | .idea 29 | .gradle 30 | local.properties 31 | *.iml 32 | 33 | # node.js 34 | # 35 | node_modules/ 36 | npm-debug.log 37 | yarn-error.log 38 | 39 | # BUCK 40 | buck-out/ 41 | \.buckd/ 42 | *.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://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 50 | 51 | fastlane/report.xml 52 | fastlane/Preview.html 53 | fastlane/screenshots 54 | -------------------------------------------------------------------------------- /example/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /example/__tests__/index.android.js: -------------------------------------------------------------------------------- 1 | import 'react-native'; 2 | import React from 'react'; 3 | import Index from '../index.android.js'; 4 | 5 | // Note: test renderer must be required after react-native. 6 | import renderer from 'react-test-renderer'; 7 | 8 | it('renders correctly', () => { 9 | const tree = renderer.create( 10 | 11 | ); 12 | }); 13 | -------------------------------------------------------------------------------- /example/__tests__/index.ios.js: -------------------------------------------------------------------------------- 1 | import 'react-native'; 2 | import React from 'react'; 3 | import Index from '../index.ios.js'; 4 | 5 | // Note: test renderer must be required after react-native. 6 | import renderer from 'react-test-renderer'; 7 | 8 | it('renders correctly', () => { 9 | const tree = renderer.create( 10 | 11 | ); 12 | }); 13 | -------------------------------------------------------------------------------- /example/android/app/BUCK: -------------------------------------------------------------------------------- 1 | # To learn about Buck see [Docs](https://buckbuild.com/). 2 | # To run your application with Buck: 3 | # - install Buck 4 | # - `npm start` - to start the packager 5 | # - `cd android` 6 | # - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"` 7 | # - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck 8 | # - `buck install -r android/app` - compile, install and run application 9 | # 10 | 11 | lib_deps = [] 12 | 13 | for jarfile in glob(['libs/*.jar']): 14 | name = 'jars__' + jarfile[jarfile.rindex('/') + 1: jarfile.rindex('.jar')] 15 | lib_deps.append(':' + name) 16 | prebuilt_jar( 17 | name = name, 18 | binary_jar = jarfile, 19 | ) 20 | 21 | for aarfile in glob(['libs/*.aar']): 22 | name = 'aars__' + aarfile[aarfile.rindex('/') + 1: aarfile.rindex('.aar')] 23 | lib_deps.append(':' + name) 24 | android_prebuilt_aar( 25 | name = name, 26 | aar = aarfile, 27 | ) 28 | 29 | android_library( 30 | name = "all-libs", 31 | exported_deps = lib_deps, 32 | ) 33 | 34 | android_library( 35 | name = "app-code", 36 | srcs = glob([ 37 | "src/main/java/**/*.java", 38 | ]), 39 | deps = [ 40 | ":all-libs", 41 | ":build_config", 42 | ":res", 43 | ], 44 | ) 45 | 46 | android_build_config( 47 | name = "build_config", 48 | package = "com.calendarsexample", 49 | ) 50 | 51 | android_resource( 52 | name = "res", 53 | package = "com.calendarsexample", 54 | res = "src/main/res", 55 | ) 56 | 57 | android_binary( 58 | name = "app", 59 | keystore = "//android/keystores:debug", 60 | manifest = "src/main/AndroidManifest.xml", 61 | package_type = "debug", 62 | deps = [ 63 | ":app-code", 64 | ], 65 | ) 66 | -------------------------------------------------------------------------------- /example/android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Disabling obfuscation is useful if you collect stack traces from production crashes 20 | # (unless you are using a system that supports de-obfuscate the stack traces). 21 | -dontobfuscate 22 | 23 | # React Native 24 | 25 | # Keep our interfaces so they can be used by other ProGuard rules. 26 | # See http://sourceforge.net/p/proguard/bugs/466/ 27 | -keep,allowobfuscation @interface com.facebook.proguard.annotations.DoNotStrip 28 | -keep,allowobfuscation @interface com.facebook.proguard.annotations.KeepGettersAndSetters 29 | -keep,allowobfuscation @interface com.facebook.common.internal.DoNotStrip 30 | 31 | # Do not strip any method/class that is annotated with @DoNotStrip 32 | -keep @com.facebook.proguard.annotations.DoNotStrip class * 33 | -keep @com.facebook.common.internal.DoNotStrip class * 34 | -keepclassmembers class * { 35 | @com.facebook.proguard.annotations.DoNotStrip *; 36 | @com.facebook.common.internal.DoNotStrip *; 37 | } 38 | 39 | -keepclassmembers @com.facebook.proguard.annotations.KeepGettersAndSetters class * { 40 | void set*(***); 41 | *** get*(); 42 | } 43 | 44 | -keep class * extends com.facebook.react.bridge.JavaScriptModule { *; } 45 | -keep class * extends com.facebook.react.bridge.NativeModule { *; } 46 | -keepclassmembers,includedescriptorclasses class * { native ; } 47 | -keepclassmembers class * { @com.facebook.react.uimanager.UIProp ; } 48 | -keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactProp ; } 49 | -keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactPropGroup ; } 50 | 51 | -dontwarn com.facebook.react.** 52 | 53 | # TextLayoutBuilder uses a non-public Android constructor within StaticLayout. 54 | # See libs/proxy/src/main/java/com/facebook/fbui/textlayoutbuilder/proxy for details. 55 | -dontwarn android.text.StaticLayout 56 | 57 | # okhttp 58 | 59 | -keepattributes Signature 60 | -keepattributes *Annotation* 61 | -keep class okhttp3.** { *; } 62 | -keep interface okhttp3.** { *; } 63 | -dontwarn okhttp3.** 64 | 65 | # okio 66 | 67 | -keep class sun.misc.Unsafe { *; } 68 | -dontwarn java.nio.file.* 69 | -dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement 70 | -dontwarn okio.** 71 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 19 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/calendarsexample/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.calendarsexample; 2 | 3 | import com.reactnativenavigation.controllers.SplashActivity; 4 | 5 | public class MainActivity extends SplashActivity { 6 | 7 | /** 8 | * Returns the name of the main component registered from JavaScript. 9 | * This is used to schedule rendering of the component. 10 | */ 11 | protected String getMainComponentName() { 12 | return "CalendarsExample"; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/calendarsexample/MainApplication.java: -------------------------------------------------------------------------------- 1 | package com.calendarsexample; 2 | import com.reactnativenavigation.NavigationApplication; 3 | 4 | import com.facebook.react.ReactPackage; 5 | 6 | import java.util.Arrays; 7 | import java.util.List; 8 | 9 | public class MainApplication extends NavigationApplication { 10 | 11 | @Override 12 | public boolean isDebug() { 13 | // Make sure you are using BuildConfig from your own application 14 | return BuildConfig.DEBUG; 15 | } 16 | 17 | protected List getPackages() { 18 | // Add additional packages you require here 19 | // No need to add RnnPackage and MainReactPackage 20 | return Arrays.asList( 21 | // eg. new VectorIconsPackage() 22 | ); 23 | } 24 | 25 | @Override 26 | public List createAdditionalReactPackages() { 27 | return getPackages(); 28 | } 29 | } -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | CalendarsExample 3 | 4 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:2.2.3' 9 | 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | mavenLocal() 18 | jcenter() 19 | maven { 20 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 21 | url "$rootDir/../node_modules/react-native/android" 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | android.useDeprecatedNdk=true 21 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/example/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip 6 | -------------------------------------------------------------------------------- /example/android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /example/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /example/android/keystores/BUCK: -------------------------------------------------------------------------------- 1 | keystore( 2 | name = "debug", 3 | properties = "debug.keystore.properties", 4 | store = "debug.keystore", 5 | visibility = [ 6 | "PUBLIC", 7 | ], 8 | ) 9 | -------------------------------------------------------------------------------- /example/android/keystores/debug.keystore.properties: -------------------------------------------------------------------------------- 1 | key.store=debug.keystore 2 | key.alias=androiddebugkey 3 | key.store.password=android 4 | key.alias.password=android 5 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'CalendarsExample' 2 | 3 | include ':react-native-navigation' 4 | project(':react-native-navigation').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-navigation/android/app/') 5 | include ':app' 6 | -------------------------------------------------------------------------------- /example/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "CalendarsExample", 3 | "displayName": "CalendarsExample" 4 | } -------------------------------------------------------------------------------- /example/index.android.js: -------------------------------------------------------------------------------- 1 | import App from './src/app'; 2 | -------------------------------------------------------------------------------- /example/index.ios.js: -------------------------------------------------------------------------------- 1 | import App from './src/app'; 2 | -------------------------------------------------------------------------------- /example/ios/CalendarsExample-tvOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UIViewControllerBasedStatusBarAppearance 38 | 39 | NSLocationWhenInUseUsageDescription 40 | 41 | NSAppTransportSecurity 42 | 43 | 44 | NSExceptionDomains 45 | 46 | localhost 47 | 48 | NSExceptionAllowsInsecureHTTPLoads 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /example/ios/CalendarsExample-tvOSTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /example/ios/CalendarsExample.xcodeproj/xcshareddata/xcschemes/CalendarsExample-tvOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 43 | 49 | 50 | 51 | 52 | 53 | 58 | 59 | 61 | 67 | 68 | 69 | 70 | 71 | 77 | 78 | 79 | 80 | 81 | 82 | 92 | 94 | 100 | 101 | 102 | 103 | 104 | 105 | 111 | 113 | 119 | 120 | 121 | 122 | 124 | 125 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /example/ios/CalendarsExample.xcodeproj/xcshareddata/xcschemes/CalendarsExample.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 43 | 49 | 50 | 51 | 52 | 53 | 58 | 59 | 61 | 67 | 68 | 69 | 70 | 71 | 77 | 78 | 79 | 80 | 81 | 82 | 92 | 94 | 100 | 101 | 102 | 103 | 104 | 105 | 111 | 113 | 119 | 120 | 121 | 122 | 124 | 125 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /example/ios/CalendarsExample/AppDelegate.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | 12 | @interface AppDelegate : UIResponder 13 | 14 | @property (nonatomic, strong) UIWindow *window; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /example/ios/CalendarsExample/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | #import 3 | 4 | // ********************************************** 5 | // *** DON'T MISS: THE NEXT LINE IS IMPORTANT *** 6 | // ********************************************** 7 | #import "RCCManager.h" 8 | 9 | // IMPORTANT: if you're getting an Xcode error that RCCManager.h isn't found, you've probably ran "npm install" 10 | // with npm ver 2. You'll need to "npm install" with npm 3 (see https://github.com/wix/react-native-navigation/issues/1) 11 | 12 | #import 13 | 14 | @implementation AppDelegate 15 | 16 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 17 | { 18 | NSURL *jsCodeLocation; 19 | #ifdef DEBUG 20 | // jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle?platform=ios&dev=true"]; 21 | jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil]; 22 | #else 23 | jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; 24 | #endif 25 | 26 | 27 | // ********************************************** 28 | // *** DON'T MISS: THIS IS HOW WE BOOTSTRAP ***** 29 | // ********************************************** 30 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 31 | self.window.backgroundColor = [UIColor whiteColor]; 32 | [[RCCManager sharedInstance] initBridgeWithBundleURL:jsCodeLocation launchOptions:launchOptions]; 33 | 34 | /* 35 | // original RN bootstrap - remove this part 36 | RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation 37 | moduleName:@"example" 38 | initialProperties:nil 39 | launchOptions:launchOptions]; 40 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 41 | UIViewController *rootViewController = [UIViewController new]; 42 | rootViewController.view = rootView; 43 | self.window.rootViewController = rootViewController; 44 | [self.window makeKeyAndVisible]; 45 | */ 46 | 47 | 48 | return YES; 49 | } 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /example/ios/CalendarsExample/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /example/ios/CalendarsExample/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /example/ios/CalendarsExample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | CalendarsExample 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSRequiresIPhoneOS 26 | 27 | NSAppTransportSecurity 28 | 29 | NSExceptionDomains 30 | 31 | localhost 32 | 33 | NSExceptionAllowsInsecureHTTPLoads 34 | 35 | 36 | 37 | 38 | NSLocationWhenInUseUsageDescription 39 | 40 | UILaunchStoryboardName 41 | LaunchScreen 42 | UIRequiredDeviceCapabilities 43 | 44 | armv7 45 | 46 | UISupportedInterfaceOrientations 47 | 48 | UIInterfaceOrientationPortrait 49 | UIInterfaceOrientationLandscapeLeft 50 | UIInterfaceOrientationLandscapeRight 51 | 52 | UIViewControllerBasedStatusBarAppearance 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /example/ios/CalendarsExample/main.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | 12 | #import "AppDelegate.h" 13 | 14 | int main(int argc, char * argv[]) { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /example/ios/CalendarsExampleTests/CalendarsExampleTests.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | #import 12 | 13 | #import 14 | #import 15 | 16 | #define TIMEOUT_SECONDS 600 17 | #define TEXT_TO_LOOK_FOR @"Welcome to React Native!" 18 | 19 | @interface CalendarsExampleTests : XCTestCase 20 | 21 | @end 22 | 23 | @implementation CalendarsExampleTests 24 | 25 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test 26 | { 27 | if (test(view)) { 28 | return YES; 29 | } 30 | for (UIView *subview in [view subviews]) { 31 | if ([self findSubviewInView:subview matching:test]) { 32 | return YES; 33 | } 34 | } 35 | return NO; 36 | } 37 | 38 | - (void)testRendersWelcomeScreen 39 | { 40 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; 41 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; 42 | BOOL foundElement = NO; 43 | 44 | __block NSString *redboxError = nil; 45 | RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { 46 | if (level >= RCTLogLevelError) { 47 | redboxError = message; 48 | } 49 | }); 50 | 51 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { 52 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 53 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 54 | 55 | foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) { 56 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { 57 | return YES; 58 | } 59 | return NO; 60 | }]; 61 | } 62 | 63 | RCTSetLogFunction(RCTDefaultLogFunction); 64 | 65 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); 66 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); 67 | } 68 | 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /example/ios/CalendarsExampleTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "CalendarsExample", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "start": "node node_modules/react-native/local-cli/cli.js start", 7 | "test": "jest" 8 | }, 9 | "dependencies": { 10 | "react": "16.6.0-alpha.8af6728", 11 | "react-native": "0.57.4", 12 | "react-native-calendars": "^1.17.5", 13 | "react-native-navigation": "^1.1.205" 14 | }, 15 | "devDependencies": { 16 | "babel-jest": "^23.6.0", 17 | "babel-preset-react-native": "^4.0.1", 18 | "jest": "20.0.4", 19 | "metro-react-native-babel-preset": "^0.49.1", 20 | "react-test-renderer": "16.0.0-alpha.12" 21 | }, 22 | "jest": { 23 | "preset": "react-native" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /example/src/app.js: -------------------------------------------------------------------------------- 1 | import {Navigation} from 'react-native-navigation'; 2 | import {registerScreens} from './screens'; 3 | registerScreens(); 4 | 5 | // eslint-disable-next-line no-console 6 | console.ignoredYellowBox = ['Remote debugger']; 7 | 8 | /* 9 | import {LocaleConfig} from 'react-native-calendars'; 10 | 11 | LocaleConfig.locales['fr'] = { 12 | monthNames: ['Janvier','Février','Mars','Avril','Mai','Juin','Juillet','Août','Septembre','Octobre','Novembre','Décembre'], 13 | monthNamesShort: ['Janv.','Févr.','Mars','Avril','Mai','Juin','Juil.','Août','Sept.','Oct.','Nov.','Déc.'], 14 | dayNames: ['Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi'], 15 | dayNamesShort: ['Dim.','Lun.','Mar.','Mer.','Jeu.','Ven.','Sam.'] 16 | }; 17 | 18 | LocaleConfig.defaultLocale = 'fr'; 19 | */ 20 | 21 | Navigation.startSingleScreenApp({ 22 | screen: { 23 | screen: 'Menu', 24 | title: 'WixCal', 25 | }, 26 | appStyle: { 27 | navBarBackgroundColor: '#00adf5', 28 | navBarTextColor: 'white', 29 | navBarButtonColor: '#ffffff', 30 | statusBarTextColorScheme: 'light', 31 | autoAdjustScrollViewInsets: true 32 | } 33 | }); -------------------------------------------------------------------------------- /example/src/screens/agenda.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { 3 | Text, 4 | View, 5 | StyleSheet 6 | } from 'react-native'; 7 | import {Agenda} from 'react-native-calendars'; 8 | 9 | export default class AgendaScreen extends Component { 10 | constructor(props) { 11 | super(props); 12 | this.state = { 13 | items: {} 14 | }; 15 | } 16 | 17 | render() { 18 | return ( 19 | ({day ? day.day: 'item'})} 39 | /> 40 | ); 41 | } 42 | 43 | loadItems(day) { 44 | setTimeout(() => { 45 | for (let i = -15; i < 85; i++) { 46 | const time = day.timestamp + i * 24 * 60 * 60 * 1000; 47 | const strTime = this.timeToString(time); 48 | if (!this.state.items[strTime]) { 49 | this.state.items[strTime] = []; 50 | const numItems = Math.floor(Math.random() * 5); 51 | for (let j = 0; j < numItems; j++) { 52 | this.state.items[strTime].push({ 53 | name: 'Item for ' + strTime, 54 | height: Math.max(50, Math.floor(Math.random() * 150)) 55 | }); 56 | } 57 | } 58 | } 59 | //console.log(this.state.items); 60 | const newItems = {}; 61 | Object.keys(this.state.items).forEach(key => {newItems[key] = this.state.items[key];}); 62 | this.setState({ 63 | items: newItems 64 | }); 65 | }, 1000); 66 | // console.log(`Load Items for ${day.year}-${day.month}`); 67 | } 68 | 69 | renderItem(item) { 70 | return ( 71 | {item.name} 72 | ); 73 | } 74 | 75 | renderEmptyDate() { 76 | return ( 77 | This is empty date! 78 | ); 79 | } 80 | 81 | rowHasChanged(r1, r2) { 82 | return r1.name !== r2.name; 83 | } 84 | 85 | timeToString(time) { 86 | const date = new Date(time); 87 | return date.toISOString().split('T')[0]; 88 | } 89 | } 90 | 91 | const styles = StyleSheet.create({ 92 | item: { 93 | backgroundColor: 'white', 94 | flex: 1, 95 | borderRadius: 5, 96 | padding: 10, 97 | marginRight: 10, 98 | marginTop: 17 99 | }, 100 | emptyDate: { 101 | height: 15, 102 | flex:1, 103 | paddingTop: 30 104 | } 105 | }); 106 | -------------------------------------------------------------------------------- /example/src/screens/calendarsList.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | 3 | import {CalendarList} from 'react-native-calendars'; 4 | 5 | export default class CalendarsList extends Component { 6 | constructor(props) { 7 | super(props); 8 | } 9 | 10 | render() { 11 | return ( 12 | 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /example/src/screens/horizontalCalendarList.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | 3 | import {CalendarList} from 'react-native-calendars'; 4 | import {View} from 'react-native'; 5 | 6 | export default class HorizontalCalendarList extends Component { 7 | constructor(props) { 8 | super(props); 9 | } 10 | 11 | render() { 12 | return ( 13 | 14 | 22 | 23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /example/src/screens/index.js: -------------------------------------------------------------------------------- 1 | import {Navigation} from 'react-native-navigation'; 2 | 3 | import MenuScreen from './menu'; 4 | import CalendarsScreen from './calendars'; 5 | import AgendaScreen from './agenda'; 6 | import CalendarsList from './calendarsList'; 7 | import HorizontalCalendarList from './horizontalCalendarList'; 8 | 9 | export function registerScreens() { 10 | Navigation.registerComponent('Menu', () => MenuScreen); 11 | Navigation.registerComponent('Calendars', () => CalendarsScreen); 12 | Navigation.registerComponent('Agenda', () => AgendaScreen); 13 | Navigation.registerComponent('CalendarsList', () => CalendarsList); 14 | Navigation.registerComponent('HorizontalCalendarList', () => HorizontalCalendarList); 15 | } 16 | -------------------------------------------------------------------------------- /example/src/screens/menu.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import { 3 | Text, 4 | View, 5 | TouchableOpacity, 6 | StyleSheet, 7 | } from 'react-native'; 8 | 9 | export default class MenuScreen extends Component { 10 | 11 | render() { 12 | return ( 13 | 14 | 15 | Calendars 16 | 17 | 18 | Calendar List 19 | 20 | 21 | Horizontal Calendar List 22 | 23 | 24 | Agenda 25 | 26 | 27 | ); 28 | } 29 | 30 | onCalendarsPress() { 31 | this.props.navigator.push({ 32 | screen: 'Calendars', 33 | title: 'Calendars' 34 | }); 35 | } 36 | 37 | onCalendarListPress() { 38 | this.props.navigator.push({ 39 | screen: 'CalendarsList', 40 | title: 'Calendar List' 41 | }); 42 | } 43 | 44 | onHorizontalCalendarListPress() { 45 | this.props.navigator.push({ 46 | screen: 'HorizontalCalendarList', 47 | title: 'Horizontal Calendars List' 48 | }); 49 | } 50 | 51 | onAgendaPress() { 52 | this.props.navigator.push({ 53 | screen: 'Agenda', 54 | title: 'Agenda' 55 | }); 56 | } 57 | } 58 | 59 | const styles = StyleSheet.create({ 60 | menu: { 61 | height: 50, 62 | justifyContent: 'center', 63 | paddingLeft: 15, 64 | borderBottomWidth: 1 65 | }, 66 | menuText: { 67 | fontSize: 18 68 | } 69 | }); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-toggle-calendar", 3 | "version": "1.0.3", 4 | "main": "src/index.js", 5 | "description": "Horizontal as well as Grid calendar built on top of react-native-calendars", 6 | "scripts": { 7 | "test": "jasmine src/*.spec.js && npm run lint", 8 | "lint": "eslint src/ example/src", 9 | "release": "node ./scripts/release.js" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/varunon9/react-native-toggle-calendar" 14 | }, 15 | "publishConfig": { 16 | "registry": "https://registry.npmjs.org/" 17 | }, 18 | "keywords": [ 19 | "react-native-calendars", 20 | "horizontal scrollable calendar", 21 | "grid-list calendar" 22 | ], 23 | "author": "Varun Kumar ", 24 | "license": "MIT", 25 | "dependencies": { 26 | "lodash.get": "^4.4.2", 27 | "lodash.isequal": "^4.5.0", 28 | "prop-types": "^15.5.10", 29 | "xdate": "^0.8.0" 30 | }, 31 | "devDependencies": { 32 | "babel-eslint": "^7.2.3", 33 | "eslint": "^3.19.0", 34 | "eslint-plugin-react": "^7.0.0", 35 | "jasmine": "^2.5.2", 36 | "react": "16.6.0-alpha.8af6728", 37 | "react-native": "0.57.4", 38 | "semver": "5.x.x", 39 | "shell-utils": "1.x.x" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.wixpress.hotels 5 | wix-react-native-calendar 6 | 1.0.0-SNAPSHOT 7 | pom 8 | Wix React Native Calendar 9 | WiX React Native Calendar 10 | 11 | 12 | com.wixpress.common 13 | wix-master-parent 14 | 100.0.0-SNAPSHOT 15 | 16 | 17 | 18 | 19 | tautvilas@wix.com 20 | Tautvilas Mecinskas 21 | tautvilas@wix.com 22 | Wix 23 | http://www.wix.com 24 | 25 | owner 26 | 27 | -2 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /scripts/release.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | const exec = require('shell-utils').exec; 3 | const semver = require('semver'); 4 | const fs = require('fs'); 5 | const _ = require('lodash'); 6 | 7 | const ONLY_ON_BRANCH = 'origin/master'; 8 | const VERSION_TAG = 'latest'; 9 | const VERSION_INC = 'minor'; 10 | 11 | function run() { 12 | if (!validateEnv()) { 13 | return; 14 | } 15 | setupGit(); 16 | createNpmRc(); 17 | versionTagAndPublish(); 18 | } 19 | 20 | function validateEnv() { 21 | if (!process.env.JENKINS_CI) { 22 | throw new Error('releasing is only available from CI'); 23 | } 24 | 25 | if (!process.env.JENKINS_MASTER) { 26 | console.log('not publishing on a different build'); 27 | return false; 28 | } 29 | 30 | if (process.env.GIT_BRANCH !== ONLY_ON_BRANCH) { 31 | console.log(`not publishing on branch ${process.env.GIT_BRANCH}`); 32 | return false; 33 | } 34 | 35 | return true; 36 | } 37 | 38 | function setupGit() { 39 | exec.execSyncSilent('git config --global push.default simple'); 40 | exec.execSyncSilent(`git config --global user.email "${process.env.GIT_EMAIL}"`); 41 | exec.execSyncSilent(`git config --global user.name "${process.env.GIT_USER}"`); 42 | const remoteUrl = new RegExp('https?://(\\S+)').exec(exec.execSyncRead('git remote -v'))[1]; 43 | exec.execSyncSilent(`git remote add deploy "https://${process.env.GIT_USER}:${process.env.GIT_TOKEN}@${remoteUrl}"`); 44 | exec.execSync(`git checkout ${ONLY_ON_BRANCH}`); 45 | } 46 | 47 | function createNpmRc() { 48 | exec.execSync('rm -f package-lock.json'); 49 | const content = ` 50 | email=\${NPM_EMAIL} 51 | //registry.npmjs.org/:_authToken=\${NPM_TOKEN} 52 | `; 53 | fs.writeFileSync('.npmrc', content); 54 | } 55 | 56 | function versionTagAndPublish() { 57 | const packageVersion = semver.clean(process.env.npm_package_version); 58 | console.log(`package version: ${packageVersion}`); 59 | 60 | const currentPublished = findCurrentPublishedVersion(); 61 | console.log(`current published version: ${currentPublished}`); 62 | 63 | const version = semver.gt(packageVersion, currentPublished) ? packageVersion : semver.inc(currentPublished, VERSION_INC); 64 | tryPublishAndTag(version); 65 | } 66 | 67 | function findCurrentPublishedVersion() { 68 | return exec.execSyncRead(`npm view ${process.env.npm_package_name} dist-tags.${VERSION_TAG}`); 69 | } 70 | 71 | function tryPublishAndTag(version) { 72 | let theCandidate = version; 73 | for (let retry = 0; retry < 5; retry++) { 74 | try { 75 | tagAndPublish(theCandidate); 76 | console.log(`Released ${theCandidate}`); 77 | return; 78 | } catch (err) { 79 | const alreadyPublished = _.includes(err.toString(), 'You cannot publish over the previously published version'); 80 | if (!alreadyPublished) { 81 | throw err; 82 | } 83 | console.log(`previously published. retrying with increased ${VERSION_INC}...`); 84 | theCandidate = semver.inc(theCandidate, VERSION_INC); 85 | } 86 | } 87 | } 88 | 89 | function tagAndPublish(newVersion) { 90 | console.log(`trying to publish ${newVersion}...`); 91 | exec.execSync(`npm --no-git-tag-version --allow-same-version version ${newVersion}`); 92 | exec.execSyncRead(`npm publish --tag ${VERSION_TAG}`); 93 | exec.execSync(`git tag -a ${newVersion} -m "${newVersion}"`); 94 | exec.execSyncSilent(`git push deploy ${newVersion} || true`); 95 | } 96 | 97 | run(); 98 | -------------------------------------------------------------------------------- /spec/runner.js: -------------------------------------------------------------------------------- 1 | import Jasmine from 'jasmine'; 2 | import path from 'path'; 3 | 4 | var jasmine = new Jasmine(); 5 | jasmine.loadConfigFile(path.resolve(__dirname, 'support', 'jasmine.json')); 6 | jasmine.execute(); 7 | -------------------------------------------------------------------------------- /spec/support/jasmine.json: -------------------------------------------------------------------------------- 1 | { 2 | "spec_dir": "src", 3 | "spec_files": [ 4 | "*.spec.js" 5 | ], 6 | "stopSpecOnExpectationFailure": false, 7 | "random": false 8 | } 9 | -------------------------------------------------------------------------------- /src/agenda/img/knob@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/src/agenda/img/knob@2x.png -------------------------------------------------------------------------------- /src/agenda/platform-style.ios.js: -------------------------------------------------------------------------------- 1 | export default function platformStyles(appStyle) { 2 | return { 3 | knob: { 4 | width: 38, 5 | height: 7, 6 | marginTop: 10, 7 | borderRadius: 3, 8 | backgroundColor: appStyle.agendaKnobColor 9 | }, 10 | weekdays: { 11 | position: 'absolute', 12 | left: 0, 13 | right: 0, 14 | top: 0, 15 | flexDirection: 'row', 16 | justifyContent: 'space-around', 17 | marginLeft: 15, 18 | marginRight: 15, 19 | paddingTop: 15, 20 | paddingBottom: 7, 21 | backgroundColor: appStyle.calendarBackground 22 | }, 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /src/agenda/platform-style.js: -------------------------------------------------------------------------------- 1 | export default function platformStyles(appStyle) { 2 | return { 3 | knob: { 4 | width: 38, 5 | height: 7, 6 | marginTop: 10, 7 | borderRadius: 3, 8 | backgroundColor: appStyle.agendaKnobColor 9 | }, 10 | weekdays: { 11 | position: 'absolute', 12 | left: 0, 13 | right: 0, 14 | top: 0, 15 | flexDirection: 'row', 16 | justifyContent: 'space-between', 17 | paddingLeft: 24, 18 | paddingRight: 24, 19 | paddingTop: 15, 20 | paddingBottom: 7, 21 | backgroundColor: appStyle.calendarBackground 22 | }, 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /src/agenda/reservation-list/reservation.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import {View, Text} from 'react-native'; 3 | import {xdateToData} from '../../interface'; 4 | import XDate from 'xdate'; 5 | import dateutils from '../../dateutils'; 6 | import styleConstructor from './style'; 7 | 8 | class ReservationListItem extends Component { 9 | constructor(props) { 10 | super(props); 11 | this.styles = styleConstructor(props.theme); 12 | } 13 | 14 | shouldComponentUpdate(nextProps) { 15 | const r1 = this.props.item; 16 | const r2 = nextProps.item; 17 | let changed = true; 18 | if (!r1 && !r2) { 19 | changed = false; 20 | } else if (r1 && r2) { 21 | if (r1.day.getTime() !== r2.day.getTime()) { 22 | changed = true; 23 | } else if (!r1.reservation && !r2.reservation) { 24 | changed = false; 25 | } else if (r1.reservation && r2.reservation) { 26 | if ((!r1.date && !r2.date) || (r1.date && r2.date)) { 27 | changed = this.props.rowHasChanged(r1.reservation, r2.reservation); 28 | } 29 | } 30 | } 31 | return changed; 32 | } 33 | 34 | renderDate(date, item) { 35 | if (this.props.renderDay) { 36 | return this.props.renderDay(date ? xdateToData(date) : undefined, item); 37 | } 38 | const today = dateutils.sameDate(date, XDate()) ? this.styles.today : undefined; 39 | if (date) { 40 | return ( 41 | 42 | {date.getDate()} 43 | {XDate.locales[XDate.defaultLocale].dayNamesShort[date.getDay()]} 44 | 45 | ); 46 | } else { 47 | return ( 48 | 49 | ); 50 | } 51 | } 52 | 53 | render() { 54 | const {reservation, date} = this.props.item; 55 | let content; 56 | if (reservation) { 57 | const firstItem = date ? true : false; 58 | content = this.props.renderItem(reservation, firstItem); 59 | } else { 60 | content = this.props.renderEmptyDate(date); 61 | } 62 | return ( 63 | 64 | {this.renderDate(date, reservation)} 65 | 66 | {content} 67 | 68 | 69 | ); 70 | } 71 | } 72 | 73 | export default ReservationListItem; 74 | -------------------------------------------------------------------------------- /src/agenda/reservation-list/style.js: -------------------------------------------------------------------------------- 1 | import {StyleSheet} from 'react-native'; 2 | import * as defaultStyle from '../../style'; 3 | 4 | const STYLESHEET_ID = 'stylesheet.agenda.list'; 5 | 6 | export default function styleConstructor(theme = {}) { 7 | const appStyle = {...defaultStyle, ...theme}; 8 | return StyleSheet.create({ 9 | container: { 10 | flexDirection: 'row' 11 | }, 12 | dayNum: { 13 | fontSize: 28, 14 | fontWeight: '200', 15 | color: appStyle.agendaDayNumColor 16 | }, 17 | dayText: { 18 | fontSize: 14, 19 | fontWeight: '300', 20 | color: appStyle.agendaDayTextColor, 21 | marginTop: -5, 22 | backgroundColor: 'rgba(0,0,0,0)' 23 | }, 24 | day: { 25 | width: 63, 26 | alignItems: 'center', 27 | justifyContent: 'flex-start', 28 | marginTop: 32 29 | }, 30 | today: { 31 | color: appStyle.agendaTodayColor 32 | }, 33 | ...(theme[STYLESHEET_ID] || {}) 34 | }); 35 | } 36 | -------------------------------------------------------------------------------- /src/agenda/style.js: -------------------------------------------------------------------------------- 1 | import {StyleSheet} from 'react-native'; 2 | import * as defaultStyle from '../style'; 3 | import platformStyles from './platform-style'; 4 | 5 | const STYLESHEET_ID = 'stylesheet.agenda.main'; 6 | 7 | export default function styleConstructor(theme = {}) { 8 | const appStyle = {...defaultStyle, ...theme}; 9 | const { knob, weekdays } = platformStyles(appStyle); 10 | return StyleSheet.create({ 11 | knob, 12 | weekdays, 13 | header: { 14 | overflow: 'hidden', 15 | justifyContent: 'flex-end', 16 | position:'absolute', 17 | height:'100%', 18 | width:'100%', 19 | }, 20 | calendar: { 21 | flex: 1, 22 | borderBottomWidth: 1, 23 | borderColor: appStyle.separatorColor 24 | }, 25 | knobContainer: { 26 | flex: 1, 27 | position: 'absolute', 28 | left: 0, 29 | right: 0, 30 | height: 24, 31 | bottom: 0, 32 | alignItems: 'center', 33 | backgroundColor: appStyle.calendarBackground 34 | }, 35 | weekday: { 36 | width: 32, 37 | textAlign: 'center', 38 | fontSize: 13, 39 | color: appStyle.textSectionTitleColor, 40 | }, 41 | reservations: { 42 | flex: 1, 43 | marginTop: 104, 44 | backgroundColor: appStyle.backgroundColor 45 | }, 46 | ...(theme[STYLESHEET_ID] || {}) 47 | }); 48 | } 49 | -------------------------------------------------------------------------------- /src/calendar-list/item.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import {Text, View} from 'react-native'; 3 | import Calendar from '../calendar'; 4 | import styleConstructor from './style'; 5 | 6 | class CalendarListItem extends Component { 7 | static defaultProps = { 8 | hideArrows: true, 9 | hideExtraDays: true, 10 | }; 11 | 12 | constructor(props) { 13 | super(props); 14 | this.style = styleConstructor(props.theme); 15 | } 16 | 17 | shouldComponentUpdate(nextProps) { 18 | const r1 = this.props.item; 19 | const r2 = nextProps.item; 20 | return r1.toString('yyyy MM') !== r2.toString('yyyy MM') || !!(r2.propbump && r2.propbump !== r1.propbump); 21 | } 22 | 23 | render() { 24 | const row = this.props.item; 25 | if (row.getTime) { 26 | return ( 27 | ); 48 | } else { 49 | const text = row.toString(); 50 | return ( 51 | 52 | {text} 53 | 54 | ); 55 | } 56 | } 57 | } 58 | 59 | export default CalendarListItem; 60 | -------------------------------------------------------------------------------- /src/calendar-list/style.js: -------------------------------------------------------------------------------- 1 | import {StyleSheet} from 'react-native'; 2 | import * as defaultStyle from '../style'; 3 | 4 | const STYLESHEET_ID = 'stylesheet.calendar-list.main'; 5 | 6 | export default function getStyle(theme={}) { 7 | const appStyle = {...defaultStyle, ...theme}; 8 | return StyleSheet.create({ 9 | container: { 10 | backgroundColor: appStyle.calendarBackground 11 | }, 12 | placeholder: { 13 | backgroundColor: appStyle.calendarBackground, 14 | alignItems: 'center', 15 | justifyContent: 'center' 16 | }, 17 | placeholderText: { 18 | fontSize: 30, 19 | fontWeight: '200', 20 | color: appStyle.dayTextColor 21 | }, 22 | calendar: { 23 | paddingLeft: 15, 24 | paddingRight: 15 25 | }, 26 | ...(theme[STYLESHEET_ID] || {}) 27 | }); 28 | } 29 | -------------------------------------------------------------------------------- /src/calendar/day/basic/index.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import { 3 | TouchableOpacity, 4 | Text, 5 | View 6 | } from 'react-native'; 7 | import PropTypes from 'prop-types'; 8 | import {shouldUpdate} from '../../../component-updater'; 9 | 10 | import styleConstructor from './style'; 11 | 12 | class Day extends Component { 13 | static propTypes = { 14 | // TODO: disabled props should be removed 15 | state: PropTypes.oneOf(['disabled', 'today', '']), 16 | 17 | // Specify theme properties to override specific styles for calendar parts. Default = {} 18 | theme: PropTypes.object, 19 | marking: PropTypes.any, 20 | onPress: PropTypes.func, 21 | onLongPress: PropTypes.func, 22 | date: PropTypes.object 23 | }; 24 | 25 | constructor(props) { 26 | super(props); 27 | this.style = styleConstructor(props.theme); 28 | this.onDayPress = this.onDayPress.bind(this); 29 | this.onDayLongPress = this.onDayLongPress.bind(this); 30 | } 31 | 32 | onDayPress() { 33 | this.props.onPress(this.props.date); 34 | } 35 | onDayLongPress() { 36 | this.props.onLongPress(this.props.date); 37 | } 38 | 39 | shouldComponentUpdate(nextProps) { 40 | return shouldUpdate(this.props, nextProps, ['state', 'children', 'marking', 'onPress', 'onLongPress']); 41 | } 42 | 43 | render() { 44 | const containerStyle = [this.style.base]; 45 | const textStyle = [this.style.text]; 46 | const dotStyle = [this.style.dot]; 47 | 48 | let marking = this.props.marking || {}; 49 | if (marking && marking.constructor === Array && marking.length) { 50 | marking = { 51 | marking: true 52 | }; 53 | } 54 | const isDisabled = typeof marking.disabled !== 'undefined' ? marking.disabled : this.props.state === 'disabled'; 55 | let dot; 56 | if (marking.marked) { 57 | dotStyle.push(this.style.visibleDot); 58 | if (marking.dotColor) { 59 | dotStyle.push({backgroundColor: marking.dotColor}); 60 | } 61 | dot = (); 62 | } 63 | 64 | if (marking.selected) { 65 | containerStyle.push(this.style.selected); 66 | if (marking.selectedColor) { 67 | containerStyle.push({backgroundColor: marking.selectedColor}); 68 | } 69 | dotStyle.push(this.style.selectedDot); 70 | textStyle.push(this.style.selectedText); 71 | } else if (isDisabled) { 72 | textStyle.push(this.style.disabledText); 73 | } else if (this.props.state === 'today') { 74 | containerStyle.push(this.style.today); 75 | textStyle.push(this.style.todayText); 76 | } 77 | 78 | return ( 79 | 86 | {String(this.props.children)} 87 | {dot} 88 | 89 | ); 90 | } 91 | } 92 | 93 | export default Day; 94 | -------------------------------------------------------------------------------- /src/calendar/day/basic/style.js: -------------------------------------------------------------------------------- 1 | import {StyleSheet, Platform} from 'react-native'; 2 | import * as defaultStyle from '../../../style'; 3 | 4 | const STYLESHEET_ID = 'stylesheet.day.basic'; 5 | 6 | export default function styleConstructor(theme={}) { 7 | const appStyle = {...defaultStyle, ...theme}; 8 | return StyleSheet.create({ 9 | base: { 10 | width: 32, 11 | height: 32, 12 | alignItems: 'center' 13 | }, 14 | text: { 15 | marginTop: Platform.OS === 'android' ? 4 : 6, 16 | fontSize: appStyle.textDayFontSize, 17 | fontFamily: appStyle.textDayFontFamily, 18 | fontWeight: '300', 19 | color: appStyle.dayTextColor, 20 | backgroundColor: 'rgba(255, 255, 255, 0)' 21 | }, 22 | alignedText: { 23 | marginTop: Platform.OS === 'android' ? 4 : 6 24 | }, 25 | selected: { 26 | backgroundColor: appStyle.selectedDayBackgroundColor, 27 | borderRadius: 16 28 | }, 29 | today: { 30 | backgroundColor: appStyle.todayBackgroundColor 31 | }, 32 | todayText: { 33 | color: appStyle.todayTextColor 34 | }, 35 | selectedText: { 36 | color: appStyle.selectedDayTextColor 37 | }, 38 | disabledText: { 39 | color: appStyle.textDisabledColor 40 | }, 41 | dot: { 42 | width: 4, 43 | height: 4, 44 | marginTop: 1, 45 | borderRadius: 2, 46 | opacity: 0 47 | }, 48 | visibleDot: { 49 | opacity: 1, 50 | backgroundColor: appStyle.dotColor 51 | }, 52 | selectedDot: { 53 | backgroundColor: appStyle.selectedDotColor 54 | }, 55 | ...(theme[STYLESHEET_ID] || {}) 56 | }); 57 | } 58 | -------------------------------------------------------------------------------- /src/calendar/day/custom/index.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import { 3 | TouchableOpacity, 4 | Text, 5 | } from 'react-native'; 6 | import PropTypes from 'prop-types'; 7 | 8 | import styleConstructor from './style'; 9 | import {shouldUpdate} from '../../../component-updater'; 10 | 11 | class Day extends Component { 12 | static propTypes = { 13 | // TODO: disabled props should be removed 14 | state: PropTypes.oneOf(['selected', 'disabled', 'today', '']), 15 | 16 | // Specify theme properties to override specific styles for calendar parts. Default = {} 17 | theme: PropTypes.object, 18 | marking: PropTypes.any, 19 | onPress: PropTypes.func, 20 | date: PropTypes.object 21 | }; 22 | 23 | constructor(props) { 24 | super(props); 25 | this.style = styleConstructor(props.theme); 26 | this.onDayPress = this.onDayPress.bind(this); 27 | this.onDayLongPress = this.onDayLongPress.bind(this); 28 | } 29 | 30 | onDayPress() { 31 | this.props.onPress(this.props.date); 32 | } 33 | onDayLongPress() { 34 | this.props.onLongPress(this.props.date); 35 | } 36 | 37 | shouldComponentUpdate(nextProps) { 38 | return shouldUpdate(this.props, nextProps, ['state', 'children', 'marking', 'onPress', 'onLongPress']); 39 | } 40 | 41 | render() { 42 | let containerStyle = [this.style.base]; 43 | let textStyle = [this.style.text]; 44 | 45 | let marking = this.props.marking || {}; 46 | if (marking && marking.constructor === Array && marking.length) { 47 | marking = { 48 | marking: true 49 | }; 50 | } 51 | const isDisabled = typeof marking.disabled !== 'undefined' ? marking.disabled : this.props.state === 'disabled'; 52 | 53 | if (marking.selected) { 54 | containerStyle.push(this.style.selected); 55 | } else if (isDisabled) { 56 | textStyle.push(this.style.disabledText); 57 | } else if (this.props.state === 'today') { 58 | containerStyle.push(this.style.today); 59 | textStyle.push(this.style.todayText); 60 | } 61 | 62 | if (marking.customStyles && typeof marking.customStyles === 'object') { 63 | const styles = marking.customStyles; 64 | if (styles.container) { 65 | if (styles.container.borderRadius === undefined) { 66 | styles.container.borderRadius = 16; 67 | } 68 | containerStyle.push(styles.container); 69 | } 70 | if (styles.text) { 71 | textStyle.push(styles.text); 72 | } 73 | } 74 | 75 | return ( 76 | 83 | {String(this.props.children)} 84 | 85 | ); 86 | } 87 | } 88 | 89 | export default Day; 90 | -------------------------------------------------------------------------------- /src/calendar/day/custom/style.js: -------------------------------------------------------------------------------- 1 | import {StyleSheet, Platform} from 'react-native'; 2 | import * as defaultStyle from '../../../style'; 3 | 4 | const STYLESHEET_ID = 'stylesheet.day.single'; 5 | 6 | export default function styleConstructor(theme={}) { 7 | const appStyle = {...defaultStyle, ...theme}; 8 | return StyleSheet.create({ 9 | base: { 10 | width: 32, 11 | height: 32, 12 | alignItems: 'center' 13 | }, 14 | text: { 15 | marginTop: Platform.OS === 'android' ? 4 : 6, 16 | fontSize: appStyle.textDayFontSize, 17 | fontFamily: appStyle.textDayFontFamily, 18 | fontWeight: '300', 19 | color: appStyle.dayTextColor, 20 | backgroundColor: 'rgba(255, 255, 255, 0)' 21 | }, 22 | alignedText: { 23 | marginTop: Platform.OS === 'android' ? 4 : 6 24 | }, 25 | selected: { 26 | backgroundColor: appStyle.selectedDayBackgroundColor, 27 | borderRadius: 16 28 | }, 29 | today: { 30 | backgroundColor: appStyle.todayBackgroundColor 31 | }, 32 | todayText: { 33 | color: appStyle.todayTextColor 34 | }, 35 | selectedText: { 36 | color: appStyle.selectedDayTextColor 37 | }, 38 | disabledText: { 39 | color: appStyle.textDisabledColor 40 | }, 41 | ...(theme[STYLESHEET_ID] || {}) 42 | }); 43 | } 44 | -------------------------------------------------------------------------------- /src/calendar/day/multi-dot/index.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import { 3 | TouchableOpacity, 4 | Text, 5 | View 6 | } from 'react-native'; 7 | import PropTypes from 'prop-types'; 8 | 9 | import {shouldUpdate} from '../../../component-updater'; 10 | 11 | import styleConstructor from './style'; 12 | 13 | class Day extends Component { 14 | static propTypes = { 15 | // TODO: disabled props should be removed 16 | state: PropTypes.oneOf(['disabled', 'today', '']), 17 | 18 | // Specify theme properties to override specific styles for calendar parts. Default = {} 19 | theme: PropTypes.object, 20 | marking: PropTypes.any, 21 | onPress: PropTypes.func, 22 | onLongPress: PropTypes.func, 23 | date: PropTypes.object 24 | }; 25 | 26 | constructor(props) { 27 | super(props); 28 | this.style = styleConstructor(props.theme); 29 | this.onDayPress = this.onDayPress.bind(this); 30 | this.onDayLongPress = this.onDayLongPress.bind(this); 31 | } 32 | 33 | onDayPress() { 34 | this.props.onPress(this.props.date); 35 | } 36 | 37 | onDayLongPress() { 38 | this.props.onLongPress(this.props.date); 39 | } 40 | 41 | shouldComponentUpdate(nextProps) { 42 | return shouldUpdate(this.props, nextProps, ['state', 'children', 'marking', 'onPress', 'onLongPress']); 43 | } 44 | 45 | renderDots(marking) { 46 | const baseDotStyle = [this.style.dot, this.style.visibleDot]; 47 | if (marking.dots && Array.isArray(marking.dots) && marking.dots.length > 0) { 48 | // Filter out dots so that we we process only those items which have key and color property 49 | const validDots = marking.dots.filter(d => (d && d.color)); 50 | return validDots.map((dot, index) => { 51 | return ( 52 | 54 | ); 55 | }); 56 | } 57 | return; 58 | } 59 | 60 | render() { 61 | const containerStyle = [this.style.base]; 62 | const textStyle = [this.style.text]; 63 | 64 | const marking = this.props.marking || {}; 65 | const dot = this.renderDots(marking); 66 | 67 | if (marking.selected) { 68 | containerStyle.push(this.style.selected); 69 | textStyle.push(this.style.selectedText); 70 | if (marking.selectedColor) { 71 | containerStyle.push({backgroundColor: marking.selectedColor}); 72 | } 73 | } else if (typeof marking.disabled !== 'undefined' ? marking.disabled : this.props.state === 'disabled') { 74 | textStyle.push(this.style.disabledText); 75 | } else if (this.props.state === 'today') { 76 | containerStyle.push(this.style.today); 77 | textStyle.push(this.style.todayText); 78 | } 79 | return ( 80 | 84 | {String(this.props.children)} 85 | {dot} 86 | 87 | ); 88 | } 89 | } 90 | 91 | export default Day; 92 | -------------------------------------------------------------------------------- /src/calendar/day/multi-dot/style.js: -------------------------------------------------------------------------------- 1 | import {StyleSheet, Platform} from 'react-native'; 2 | import * as defaultStyle from '../../../style'; 3 | 4 | const STYLESHEET_ID = 'stylesheet.day.multiDot'; 5 | 6 | export default function styleConstructor(theme={}) { 7 | const appStyle = {...defaultStyle, ...theme}; 8 | return StyleSheet.create({ 9 | base: { 10 | width: 32, 11 | height: 32, 12 | alignItems: 'center' 13 | }, 14 | text: { 15 | marginTop: 4, 16 | fontSize: appStyle.textDayFontSize, 17 | fontFamily: appStyle.textDayFontFamily, 18 | fontWeight: '300', 19 | color: appStyle.dayTextColor, 20 | backgroundColor: 'rgba(255, 255, 255, 0)' 21 | }, 22 | alignedText: { 23 | marginTop: Platform.OS === 'android' ? 4 : 6 24 | }, 25 | selected: { 26 | backgroundColor: appStyle.selectedDayBackgroundColor, 27 | borderRadius: 16 28 | }, 29 | today: { 30 | backgroundColor: appStyle.todayBackgroundColor 31 | }, 32 | todayText: { 33 | color: appStyle.todayTextColor 34 | }, 35 | selectedText: { 36 | color: appStyle.selectedDayTextColor 37 | }, 38 | disabledText: { 39 | color: appStyle.textDisabledColor 40 | }, 41 | dot: { 42 | width: 4, 43 | height: 4, 44 | marginTop: 1, 45 | marginLeft: 1, 46 | marginRight: 1, 47 | borderRadius: 2, 48 | opacity: 0 49 | }, 50 | visibleDot: { 51 | opacity: 1, 52 | backgroundColor: appStyle.dotColor 53 | }, 54 | selectedDot: { 55 | backgroundColor: appStyle.selectedDotColor 56 | }, 57 | ...(theme[STYLESHEET_ID] || {}) 58 | }); 59 | } 60 | -------------------------------------------------------------------------------- /src/calendar/day/multi-period/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { TouchableOpacity, Text, View } from 'react-native'; 3 | import PropTypes from 'prop-types'; 4 | import {shouldUpdate} from '../../../component-updater'; 5 | 6 | import styleConstructor from './style'; 7 | 8 | class Day extends Component { 9 | static propTypes = { 10 | // TODO: disabled props should be removed 11 | state: PropTypes.oneOf(['disabled', 'today', '']), 12 | 13 | // Specify theme properties to override specific styles for calendar parts. Default = {} 14 | theme: PropTypes.object, 15 | marking: PropTypes.any, 16 | onPress: PropTypes.func, 17 | date: PropTypes.object, 18 | }; 19 | 20 | constructor(props) { 21 | super(props); 22 | this.style = styleConstructor(props.theme); 23 | this.onDayPress = this.onDayPress.bind(this); 24 | } 25 | 26 | onDayPress() { 27 | this.props.onPress(this.props.date); 28 | } 29 | 30 | shouldComponentUpdate(nextProps) { 31 | return shouldUpdate(this.props, nextProps, ['state', 'children', 'marking', 'onPress', 'onLongPress']); 32 | } 33 | 34 | renderPeriods(marking) { 35 | const baseDotStyle = [this.style.dot, this.style.visibleDot]; 36 | if ( 37 | marking.periods && 38 | Array.isArray(marking.periods) && 39 | marking.periods.length > 0 40 | ) { 41 | // Filter out dots so that we we process only those items which have key and color property 42 | const validPeriods = marking.periods.filter(d => d && d.color); 43 | return validPeriods.map((period, index) => { 44 | const style = [ 45 | ...baseDotStyle, 46 | { 47 | backgroundColor: period.color, 48 | }, 49 | ]; 50 | if (period.startingDay) { 51 | style.push({ 52 | borderTopLeftRadius: 2, 53 | borderBottomLeftRadius: 2, 54 | marginLeft: 4, 55 | }); 56 | } 57 | if (period.endingDay) { 58 | style.push({ 59 | borderTopRightRadius: 2, 60 | borderBottomRightRadius: 2, 61 | marginRight: 4, 62 | }); 63 | } 64 | return ; 65 | }); 66 | } 67 | return; 68 | } 69 | 70 | render() { 71 | const containerStyle = [this.style.base]; 72 | const textStyle = [this.style.text]; 73 | 74 | const marking = this.props.marking || {}; 75 | const periods = this.renderPeriods(marking); 76 | 77 | if (marking.selected) { 78 | containerStyle.push(this.style.selected); 79 | textStyle.push(this.style.selectedText); 80 | } else if ( 81 | typeof marking.disabled !== 'undefined' 82 | ? marking.disabled 83 | : this.props.state === 'disabled' 84 | ) { 85 | textStyle.push(this.style.disabledText); 86 | } else if (this.props.state === 'today') { 87 | containerStyle.push(this.style.today); 88 | textStyle.push(this.style.todayText); 89 | } 90 | return ( 91 | 95 | 96 | 97 | {String(this.props.children)} 98 | 99 | 100 | 104 | {periods} 105 | 106 | 107 | ); 108 | } 109 | } 110 | 111 | export default Day; 112 | -------------------------------------------------------------------------------- /src/calendar/day/multi-period/style.js: -------------------------------------------------------------------------------- 1 | import { StyleSheet, Platform } from 'react-native'; 2 | import * as defaultStyle from '../../../style'; 3 | 4 | const STYLESHEET_ID = 'stylesheet.day.basic'; 5 | 6 | export default function styleConstructor(theme = {}) { 7 | const appStyle = { ...defaultStyle, ...theme }; 8 | return StyleSheet.create({ 9 | base: { 10 | width: 32, 11 | height: 32, 12 | alignItems: 'center', 13 | }, 14 | text: { 15 | marginTop: Platform.OS === 'android' ? 4 : 6, 16 | fontSize: appStyle.textDayFontSize, 17 | fontFamily: appStyle.textDayFontFamily, 18 | fontWeight: '300', 19 | color: appStyle.dayTextColor, 20 | backgroundColor: 'rgba(255, 255, 255, 0)', 21 | }, 22 | alignedText: { 23 | marginTop: Platform.OS === 'android' ? 4 : 6, 24 | }, 25 | selected: { 26 | backgroundColor: appStyle.selectedDayBackgroundColor, 27 | borderRadius: 16, 28 | }, 29 | today: { 30 | backgroundColor: appStyle.todayBackgroundColor 31 | }, 32 | todayText: { 33 | color: appStyle.todayTextColor, 34 | }, 35 | selectedText: { 36 | color: appStyle.selectedDayTextColor, 37 | }, 38 | disabledText: { 39 | color: appStyle.textDisabledColor, 40 | }, 41 | dot: { 42 | // width: 42, 43 | height: 4, 44 | marginVertical: 1, 45 | // borderRadius: 2, 46 | opacity: 0, 47 | }, 48 | leftFiller: { 49 | width: 4, 50 | height: 4, 51 | marginTop: 1, 52 | marginRight: -2, 53 | }, 54 | rightFiller: { 55 | width: 4, 56 | height: 4, 57 | marginTop: 1, 58 | marginLeft: -2, 59 | }, 60 | rounded: { 61 | borderRadius: 2, 62 | }, 63 | visibleDot: { 64 | opacity: 1, 65 | backgroundColor: appStyle.dotColor, 66 | }, 67 | selectedDot: { 68 | backgroundColor: appStyle.selectedDotColor, 69 | }, 70 | startingPeriod: { 71 | width: 18, 72 | height: 4, 73 | marginTop: 1, 74 | borderRadius: 2, 75 | opacity: 0, 76 | }, 77 | ...(theme[STYLESHEET_ID] || {}), 78 | }); 79 | } 80 | -------------------------------------------------------------------------------- /src/calendar/day/period/style.js: -------------------------------------------------------------------------------- 1 | import {StyleSheet} from 'react-native'; 2 | import * as defaultStyle from '../../../style'; 3 | 4 | const STYLESHEET_ID = 'stylesheet.day.period'; 5 | 6 | const FILLER_HEIGHT = 34; 7 | 8 | export default function styleConstructor(theme={}) { 9 | const appStyle = {...defaultStyle, ...theme}; 10 | return StyleSheet.create({ 11 | wrapper: { 12 | alignItems: 'center', 13 | alignSelf: 'stretch', 14 | marginLeft: -1 15 | }, 16 | base: { 17 | //borderWidth: 1, 18 | width: 38, 19 | height: FILLER_HEIGHT, 20 | alignItems: 'center' 21 | }, 22 | fillers: { 23 | position: 'absolute', 24 | height: FILLER_HEIGHT, 25 | flexDirection: 'row', 26 | left: 0, 27 | right: 0 28 | }, 29 | leftFiller: { 30 | height: FILLER_HEIGHT, 31 | flex: 1 32 | }, 33 | rightFiller: { 34 | height: FILLER_HEIGHT, 35 | flex: 1 36 | }, 37 | text: { 38 | marginTop: 7, 39 | fontSize: appStyle.textDayFontSize, 40 | fontFamily: appStyle.textDayFontFamily, 41 | fontWeight: '300', 42 | color: appStyle.dayTextColor || '#2d4150', 43 | backgroundColor: 'rgba(255, 255, 255, 0)' 44 | }, 45 | today: { 46 | backgroundColor: appStyle.todayBackgroundColor 47 | }, 48 | todayText: { 49 | fontWeight: '500', 50 | color: theme.todayTextColor || appStyle.dayTextColor, 51 | //color: appStyle.textLinkColor 52 | }, 53 | disabledText: { 54 | color: appStyle.textDisabledColor 55 | }, 56 | quickAction: { 57 | backgroundColor: 'white', 58 | borderWidth: 1, 59 | borderColor: '#c1e4fe' 60 | }, 61 | quickActionText: { 62 | marginTop: 6, 63 | color: appStyle.textColor 64 | }, 65 | firstQuickAction: { 66 | backgroundColor: appStyle.textLinkColor 67 | }, 68 | firstQuickActionText: { 69 | color: 'white' 70 | }, 71 | naText: { 72 | color: '#b6c1cd' 73 | }, 74 | ...(theme[STYLESHEET_ID] || {}) 75 | }); 76 | } 77 | -------------------------------------------------------------------------------- /src/calendar/header/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { ActivityIndicator } from 'react-native'; 3 | import { View, Text, TouchableOpacity, Image } from 'react-native'; 4 | import XDate from 'xdate'; 5 | import PropTypes from 'prop-types'; 6 | import styleConstructor from './style'; 7 | import { weekDayNames } from '../../dateutils'; 8 | import { 9 | CHANGE_MONTH_LEFT_ARROW, 10 | CHANGE_MONTH_RIGHT_ARROW 11 | } from '../../testIDs'; 12 | 13 | class CalendarHeader extends Component { 14 | static propTypes = { 15 | theme: PropTypes.object, 16 | hideArrows: PropTypes.bool, 17 | month: PropTypes.instanceOf(XDate), 18 | addMonth: PropTypes.func, 19 | showIndicator: PropTypes.bool, 20 | firstDay: PropTypes.number, 21 | renderArrow: PropTypes.func, 22 | hideDayNames: PropTypes.bool, 23 | weekNumbers: PropTypes.bool, 24 | onPressArrowLeft: PropTypes.func, 25 | onPressArrowRight: PropTypes.func 26 | }; 27 | 28 | static defaultProps = { 29 | monthFormat: 'MMMM yyyy', 30 | }; 31 | 32 | constructor(props) { 33 | super(props); 34 | this.style = styleConstructor(props.theme); 35 | this.addMonth = this.addMonth.bind(this); 36 | this.substractMonth = this.substractMonth.bind(this); 37 | this.onPressLeft = this.onPressLeft.bind(this); 38 | this.onPressRight = this.onPressRight.bind(this); 39 | } 40 | 41 | addMonth() { 42 | this.props.addMonth(1); 43 | } 44 | 45 | substractMonth() { 46 | this.props.addMonth(-1); 47 | } 48 | 49 | shouldComponentUpdate(nextProps) { 50 | if ( 51 | nextProps.month.toString('yyyy MM') !== 52 | this.props.month.toString('yyyy MM') 53 | ) { 54 | return true; 55 | } 56 | if (nextProps.showIndicator !== this.props.showIndicator) { 57 | return true; 58 | } 59 | if (nextProps.hideDayNames !== this.props.hideDayNames) { 60 | return true; 61 | } 62 | return false; 63 | } 64 | 65 | onPressLeft() { 66 | const {onPressArrowLeft} = this.props; 67 | if(typeof onPressArrowLeft === 'function') { 68 | return onPressArrowLeft(this.substractMonth); 69 | } 70 | return this.substractMonth(); 71 | } 72 | 73 | onPressRight() { 74 | const {onPressArrowRight} = this.props; 75 | if(typeof onPressArrowRight === 'function') { 76 | return onPressArrowRight(this.addMonth); 77 | } 78 | return this.addMonth(); 79 | } 80 | 81 | render() { 82 | let leftArrow = ; 83 | let rightArrow = ; 84 | let weekDaysNames = weekDayNames(this.props.firstDay); 85 | if (!this.props.hideArrows) { 86 | leftArrow = ( 87 | 93 | {this.props.renderArrow 94 | ? this.props.renderArrow('left') 95 | : } 99 | 100 | ); 101 | rightArrow = ( 102 | 108 | {this.props.renderArrow 109 | ? this.props.renderArrow('right') 110 | : } 114 | 115 | ); 116 | } 117 | let indicator; 118 | if (this.props.showIndicator) { 119 | indicator = ; 120 | } 121 | return ( 122 | 123 | 124 | {leftArrow} 125 | 126 | 127 | {this.props.month.toString(this.props.monthFormat)} 128 | 129 | {indicator} 130 | 131 | {rightArrow} 132 | 133 | { 134 | !this.props.hideDayNames && 135 | 136 | {this.props.weekNumbers && } 137 | {weekDaysNames.map((day, idx) => ( 138 | {day} 139 | ))} 140 | 141 | } 142 | 143 | ); 144 | } 145 | } 146 | 147 | export default CalendarHeader; 148 | -------------------------------------------------------------------------------- /src/calendar/header/style.js: -------------------------------------------------------------------------------- 1 | import {StyleSheet, Platform} from 'react-native'; 2 | import * as defaultStyle from '../../style'; 3 | 4 | const STYLESHEET_ID = 'stylesheet.calendar.header'; 5 | 6 | export default function(theme={}) { 7 | const appStyle = {...defaultStyle, ...theme}; 8 | return StyleSheet.create({ 9 | header: { 10 | flexDirection: 'row', 11 | justifyContent: 'space-between', 12 | paddingLeft: 10, 13 | paddingRight: 10, 14 | alignItems: 'center' 15 | }, 16 | monthText: { 17 | fontSize: appStyle.textMonthFontSize, 18 | fontFamily: appStyle.textMonthFontFamily, 19 | fontWeight: appStyle.textMonthFontWeight, 20 | color: appStyle.monthTextColor, 21 | margin: 10 22 | }, 23 | arrow: { 24 | padding: 10 25 | }, 26 | arrowImage: { 27 | ...Platform.select({ 28 | ios: { 29 | tintColor: appStyle.arrowColor 30 | }, 31 | android: { 32 | tintColor: appStyle.arrowColor 33 | } 34 | }) 35 | }, 36 | week: { 37 | marginTop: 7, 38 | flexDirection: 'row', 39 | justifyContent: 'space-around' 40 | }, 41 | dayHeader: { 42 | marginTop: 2, 43 | marginBottom: 7, 44 | width: 32, 45 | textAlign: 'center', 46 | fontSize: appStyle.textDayHeaderFontSize, 47 | fontFamily: appStyle.textDayHeaderFontFamily, 48 | color: appStyle.textSectionTitleColor 49 | }, 50 | ...(theme[STYLESHEET_ID] || {}) 51 | }); 52 | } 53 | -------------------------------------------------------------------------------- /src/calendar/img/next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/src/calendar/img/next.png -------------------------------------------------------------------------------- /src/calendar/img/next@1.5x.android.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/src/calendar/img/next@1.5x.android.png -------------------------------------------------------------------------------- /src/calendar/img/next@2x.android.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/src/calendar/img/next@2x.android.png -------------------------------------------------------------------------------- /src/calendar/img/next@2x.ios.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/src/calendar/img/next@2x.ios.png -------------------------------------------------------------------------------- /src/calendar/img/next@3x.android.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/src/calendar/img/next@3x.android.png -------------------------------------------------------------------------------- /src/calendar/img/next@4x.android.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/src/calendar/img/next@4x.android.png -------------------------------------------------------------------------------- /src/calendar/img/previous.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/src/calendar/img/previous.png -------------------------------------------------------------------------------- /src/calendar/img/previous@1.5x.android.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/src/calendar/img/previous@1.5x.android.png -------------------------------------------------------------------------------- /src/calendar/img/previous@2x.android.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/src/calendar/img/previous@2x.android.png -------------------------------------------------------------------------------- /src/calendar/img/previous@2x.ios.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/src/calendar/img/previous@2x.ios.png -------------------------------------------------------------------------------- /src/calendar/img/previous@3x.android.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/src/calendar/img/previous@3x.android.png -------------------------------------------------------------------------------- /src/calendar/img/previous@4x.android.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/react-native-toggle-calendar/247f53620c3d0de7e152333dc44901b924f03c9c/src/calendar/img/previous@4x.android.png -------------------------------------------------------------------------------- /src/calendar/style.js: -------------------------------------------------------------------------------- 1 | import {StyleSheet} from 'react-native'; 2 | import * as defaultStyle from '../style'; 3 | 4 | const STYLESHEET_ID = 'stylesheet.calendar.main'; 5 | 6 | export default function getStyle(theme={}) { 7 | const appStyle = {...defaultStyle, ...theme}; 8 | return StyleSheet.create({ 9 | container: { 10 | paddingLeft: 5, 11 | paddingRight: 5, 12 | backgroundColor: appStyle.calendarBackground 13 | }, 14 | monthView: { 15 | backgroundColor: appStyle.calendarBackground 16 | }, 17 | week: { 18 | marginTop: 7, 19 | marginBottom: 7, 20 | flexDirection: 'row', 21 | justifyContent: 'space-around' 22 | }, 23 | loaderContainer: { 24 | width: '100%', 25 | height: '100%', 26 | position: 'absolute' 27 | }, 28 | ...(theme[STYLESHEET_ID] || {}) 29 | }); 30 | } 31 | 32 | -------------------------------------------------------------------------------- /src/calendar/updater.js: -------------------------------------------------------------------------------- 1 | import {parseDate} from '../interface'; 2 | 3 | export default function shouldComponentUpdate(nextProps, nextState) { 4 | let shouldUpdate = (nextProps.selected || []).reduce((prev, next, i) => { 5 | const currentSelected = (this.props.selected || [])[i]; 6 | if (!currentSelected || !next || parseDate(currentSelected).getTime() !== parseDate(next).getTime()) { 7 | return { 8 | update: true, 9 | field: 'selected' 10 | }; 11 | } 12 | return prev; 13 | }, {update: false}); 14 | 15 | shouldUpdate = ['markedDates', 'hideExtraDays'].reduce((prev, next) => { 16 | if (!prev.update && nextProps[next] !== this.props[next]) { 17 | return { 18 | update: true, 19 | field: next 20 | }; 21 | } 22 | return prev; 23 | }, shouldUpdate); 24 | 25 | shouldUpdate = ['minDate', 'maxDate', 'current'].reduce((prev, next) => { 26 | const prevDate = parseDate(this.props[next]); 27 | const nextDate = parseDate(nextProps[next]); 28 | if (prev.update) { 29 | return prev; 30 | } else if (prevDate !== nextDate) { 31 | if (prevDate && nextDate && prevDate.getTime() === nextDate.getTime()) { 32 | return prev; 33 | } else { 34 | return { 35 | update: true, 36 | field: next 37 | }; 38 | } 39 | } 40 | return prev; 41 | }, shouldUpdate); 42 | 43 | if (nextState.currentMonth !== this.state.currentMonth) { 44 | shouldUpdate = { 45 | update: true, 46 | field: 'current' 47 | }; 48 | } 49 | 50 | if (nextState.horizontal !== this.state.horizontal) { 51 | shouldUpdate = { 52 | update: true, 53 | field: 'horizontal' 54 | }; 55 | } 56 | //console.log(shouldUpdate.field, shouldUpdate.update); 57 | return shouldUpdate.update; 58 | } 59 | -------------------------------------------------------------------------------- /src/component-updater.js: -------------------------------------------------------------------------------- 1 | const get = require('lodash.get'); 2 | const isEqual = require('lodash.isequal'); 3 | 4 | function shouldUpdate(a, b, paths) { 5 | for (let i = 0; i < paths.length; i++) { 6 | const equals = isEqual(get(a, paths[i]), get(b, paths[i])); 7 | if (!equals) { 8 | return true; 9 | } 10 | } 11 | return false; 12 | } 13 | 14 | module.exports = { 15 | shouldUpdate 16 | }; 17 | -------------------------------------------------------------------------------- /src/component-updater.spec.js: -------------------------------------------------------------------------------- 1 | const {shouldUpdate} = require('./component-updater'); 2 | 3 | describe('component updater', () => { 4 | it('should return true if two different objects are provided with same path', async () => { 5 | const a = {details: 'whoa'}; 6 | const b = {details: 'whoax'}; 7 | const paths = ['details']; 8 | 9 | expect(shouldUpdate(a, b, paths)).toEqual(true); 10 | }); 11 | 12 | it('should return false if two same objects are provided with same path', async () => { 13 | const a = {details: 'whoa'}; 14 | const b = {details: 'whoa'}; 15 | const paths = ['details']; 16 | 17 | expect(shouldUpdate(a, b, paths)).toEqual(false); 18 | }); 19 | 20 | it('should return true if two different deep objects are provided with same path', async () => { 21 | const a = {details: {x: {y: 1}}}; 22 | const b = {details: {x: {y: 2}}}; 23 | const paths = ['details']; 24 | 25 | expect(shouldUpdate(a, b, paths)).toEqual(true); 26 | }); 27 | 28 | it('should return false if two same deep objects are provided with same path', async () => { 29 | const a = {details: {x: {y: 1}}}; 30 | const b = {details: {x: {y: 1}}}; 31 | const paths = ['details']; 32 | 33 | expect(shouldUpdate(a, b, paths)).toEqual(false); 34 | }); 35 | 36 | it('should return false if several same deep objects are provided with same path', async () => { 37 | const a = {details: {x: {y: 1}}, details2: {x: {y: 2}}, porage: 'yes'}; 38 | const b = {details: {x: {y: 1}}, details2: {x: {y: 2}}, porage: 'yes'}; 39 | const paths = ['details', 'details2', 'porage']; 40 | 41 | expect(shouldUpdate(a, b, paths)).toEqual(false); 42 | }); 43 | 44 | it('should return true if several different deep objects are provided with same path', async () => { 45 | const a = {details: {x: {y: 1}}, details2: {x: {y: 2}}, porage: 'yes'}; 46 | const b = {details: {x: {y: 1}}, details2: {x: {y: 2}}, porage: 'no'}; 47 | const paths = ['details', 'details2', 'porage']; 48 | 49 | expect(shouldUpdate(a, b, paths)).toEqual(true); 50 | }); 51 | 52 | it('should return true if two different deep props of objects are provided with same path', async () => { 53 | const a = {details: {x: {y: 1}}, details2: {x: {y: 2}}, porage: 'yes'}; 54 | const b = {details: {x: {y: 2}}, details2: {x: {y: 2}}, porage: 'yes'}; 55 | const paths = ['details.x.y', 'details2', 'porage']; 56 | 57 | expect(shouldUpdate(a, b, paths)).toEqual(true); 58 | }); 59 | 60 | it('should return false if two same deep props of objects are provided with same path', async () => { 61 | const a = {details: {x: {y: 1}, y: '1'}, details2: {x: {y: 2}}, porage: 'yes'}; 62 | const b = {details: {x: {y: 1}}, details2: {x: {y: 2}}, porage: 'yes'}; 63 | const paths = ['details.x.y', 'details2', 'porage']; 64 | 65 | expect(shouldUpdate(a, b, paths)).toEqual(false); 66 | }); 67 | }); 68 | -------------------------------------------------------------------------------- /src/dateutils.js: -------------------------------------------------------------------------------- 1 | const XDate = require('xdate'); 2 | 3 | function sameMonth(a, b) { 4 | return a instanceof XDate && b instanceof XDate && 5 | a.getFullYear() === b.getFullYear() && 6 | a.getMonth() === b.getMonth(); 7 | } 8 | 9 | function sameDate(a, b) { 10 | return a instanceof XDate && b instanceof XDate && 11 | a.getFullYear() === b.getFullYear() && 12 | a.getMonth() === b.getMonth() && 13 | a.getDate() === b.getDate(); 14 | } 15 | 16 | function isGTE(a, b) { 17 | return b.diffDays(a) > -1; 18 | } 19 | 20 | function isLTE(a, b) { 21 | return a.diffDays(b) > -1; 22 | } 23 | 24 | function fromTo(a, b) { 25 | const days = []; 26 | let from = +a, to = +b; 27 | for (; from <= to; from = new XDate(from, true).addDays(1).getTime()) { 28 | days.push(new XDate(from, true)); 29 | } 30 | return days; 31 | } 32 | 33 | function month(xd) { 34 | const year = xd.getFullYear(), month = xd.getMonth(); 35 | const days = new Date(year, month + 1, 0).getDate(); 36 | 37 | const firstDay = new XDate(year, month, 1, 0, 0, 0, true); 38 | const lastDay = new XDate(year, month, days, 0, 0, 0, true); 39 | 40 | return fromTo(firstDay, lastDay); 41 | } 42 | 43 | function weekDayNames(firstDayOfWeek = 0) { 44 | let weekDaysNames = XDate.locales[XDate.defaultLocale].dayNamesShort; 45 | const dayShift = firstDayOfWeek % 7; 46 | if (dayShift) { 47 | weekDaysNames = weekDaysNames.slice(dayShift).concat(weekDaysNames.slice(0, dayShift)); 48 | } 49 | return weekDaysNames; 50 | } 51 | 52 | function page(xd, firstDayOfWeek) { 53 | const days = month(xd); 54 | let before = [], after = []; 55 | 56 | const fdow = ((7 + firstDayOfWeek) % 7) || 7; 57 | const ldow = (fdow + 6) % 7; 58 | 59 | firstDayOfWeek = firstDayOfWeek || 0; 60 | 61 | const from = days[0].clone(); 62 | if (from.getDay() !== fdow) { 63 | from.addDays(-(from.getDay() + 7 - fdow) % 7); 64 | } 65 | 66 | const to = days[days.length - 1].clone(); 67 | const day = to.getDay(); 68 | if (day !== ldow) { 69 | to.addDays((ldow + 7 - day) % 7); 70 | } 71 | 72 | if (isLTE(from, days[0])) { 73 | before = fromTo(from, days[0]); 74 | } 75 | 76 | if (isGTE(to, days[days.length - 1])) { 77 | after = fromTo(days[days.length - 1], to); 78 | } 79 | 80 | return before.concat(days.slice(1, days.length - 1), after); 81 | } 82 | 83 | module.exports = { 84 | weekDayNames, 85 | sameMonth, 86 | sameDate, 87 | month, 88 | page, 89 | fromTo, 90 | isLTE, 91 | isGTE 92 | }; 93 | -------------------------------------------------------------------------------- /src/dateutils.spec.js: -------------------------------------------------------------------------------- 1 | const XDate = require('xdate'); 2 | const dateutils = require('./dateutils'); 3 | 4 | describe('dateutils', function () { 5 | describe('sameMonth()', function () { 6 | it('2014-01-01 === 2014-01-10', function () { 7 | const a = XDate(2014, 0, 1, true); 8 | const b = XDate(2014, 0, 10, true); 9 | expect(dateutils.sameMonth(a, b)).toEqual(true); 10 | }); 11 | it('for non-XDate instances is false', function () { 12 | expect(dateutils.sameMonth('a', 'b')).toEqual(false); 13 | expect(dateutils.sameMonth(123, 345)).toEqual(false); 14 | expect(dateutils.sameMonth(null, false)).toEqual(false); 15 | 16 | const a = XDate(2014, 0, 1, true); 17 | const b = XDate(2014, 0, 10, true); 18 | expect(dateutils.sameMonth(a, undefined)).toEqual(false); 19 | expect(dateutils.sameMonth(null, b)).toEqual(false); 20 | }); 21 | }); 22 | 23 | describe('isLTE()', function () { 24 | it('2014-01-20 >= 2013-12-31', function () { 25 | const a = XDate(2013, 12, 31); 26 | const b = XDate(2014, 1, 20); 27 | expect(dateutils.isLTE(a, b)).toBe(true); 28 | }); 29 | 30 | it('2014-10-20 >= 2014-10-19', function () { 31 | const a = XDate(2014, 10, 19); 32 | const b = XDate(2014, 10, 20); 33 | expect(dateutils.isLTE(a, b)).toBe(true); 34 | }); 35 | 36 | it('2014-10-20 >= 2014-09-30', function () { 37 | const a = XDate(2014, 9, 30); 38 | const b = XDate(2014, 10, 20); 39 | expect(dateutils.isLTE(a, b)).toBe(true); 40 | }); 41 | 42 | it('works for dates that differ by less than a day', function () { 43 | const a = XDate(2014, 9, 30, 0, 1, 0); 44 | const b = XDate(2014, 9, 30, 1, 0, 1); 45 | expect(dateutils.isLTE(a, b)).toBe(true); 46 | expect(dateutils.isLTE(b, a)).toBe(true); 47 | }); 48 | }); 49 | 50 | describe('isGTE()', function () { 51 | it('2014-01-20 >= 2013-12-31', function () { 52 | const a = XDate(2013, 12, 31); 53 | const b = XDate(2014, 1, 20); 54 | expect(dateutils.isGTE(b, a)).toBe(true); 55 | }); 56 | 57 | it('2014-10-20 >= 2014-10-19', function () { 58 | const a = XDate(2014, 10, 19); 59 | const b = XDate(2014, 10, 20); 60 | expect(dateutils.isGTE(b, a)).toBe(true); 61 | }); 62 | 63 | it('2014-10-20 >= 2014-09-30', function () { 64 | const a = XDate(2014, 9, 30); 65 | const b = XDate(2014, 10, 20); 66 | expect(dateutils.isGTE(b, a)).toBe(true); 67 | }); 68 | 69 | it('works for dates that differ by less than a day', function () { 70 | const a = XDate(2014, 9, 30, 0, 1, 0); 71 | const b = XDate(2014, 9, 30, 1, 0, 1); 72 | expect(dateutils.isGTE(a, b)).toBe(true); 73 | expect(dateutils.isGTE(b, a)).toBe(true); 74 | }); 75 | }); 76 | 77 | describe('month()', function () { 78 | it('2014 May', function () { 79 | const days = dateutils.month(XDate(2014, 4, 1)); 80 | expect(days.length).toBe(31); 81 | }); 82 | 83 | it('2014 August', function () { 84 | const days = dateutils.month(XDate(2014, 7, 1)); 85 | expect(days.length).toBe(31); 86 | }); 87 | }); 88 | 89 | describe('page()', function () { 90 | it('2014 March', function () { 91 | const days = dateutils.page(XDate(2014, 2, 23, true)); 92 | expect(days.length).toBe(42); 93 | expect(days[0].toString()) 94 | .toBe(XDate(2014, 1, 23, 0, 0, 0, true).toString()); 95 | expect(days[days.length - 1].toString()) 96 | .toBe(XDate(2014, 3, 5, 0, 0, 0, true).toString()); 97 | }); 98 | 99 | it('2014 May', function () { 100 | const days = dateutils.page(XDate(2014, 4, 23)); 101 | expect(days.length).toBe(35); 102 | }); 103 | 104 | it('2014 June', function () { 105 | const days = dateutils.page(XDate(2014, 5, 23)); 106 | expect(days.length).toBe(35); 107 | }); 108 | 109 | it('2014 August', function () { 110 | const days = dateutils.page(XDate(2014, 7, 23)); 111 | expect(days.length).toBe(42); 112 | }); 113 | 114 | it('2014 October', function () { 115 | const days = dateutils.page(XDate(2014, 9, 21)); 116 | expect(days.length).toBe(35); 117 | }); 118 | 119 | it('has all days in ascending order', function () { 120 | let days, i, len; 121 | 122 | days = dateutils.page(XDate(2014, 2, 1)); 123 | for (i = 0, len = days.length - 1; i < len; i++) { 124 | expect(days[i].diffDays(days[i + 1])).toBe(1); 125 | } 126 | days = dateutils.page(XDate(2014, 9, 1)); 127 | for (i = 0, len = days.length - 1; i < len; i++) { 128 | expect(days[i].diffDays(days[i + 1])).toBe(1); 129 | } 130 | }); 131 | }); 132 | 133 | }); 134 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | export { default as Calendar } from './calendar'; 2 | export { default as CalendarList } from './calendar-list'; 3 | export { default as Agenda } from './agenda'; 4 | export { default as LocaleConfig } from 'xdate'; 5 | -------------------------------------------------------------------------------- /src/input.js: -------------------------------------------------------------------------------- 1 | export class VelocityTracker { 2 | constructor() { 3 | this.history = []; 4 | this.lastPosition = undefined; 5 | this.lastTimestamp = undefined; 6 | } 7 | 8 | add(position) { 9 | const timestamp = new Date().valueOf(); 10 | if (this.lastPosition && timestamp > this.lastTimestamp) { 11 | const diff = position - this.lastPosition; 12 | if (diff > 0.001 || diff < -0.001) { 13 | this.history.push(diff / (timestamp - this.lastTimestamp)); 14 | } 15 | } 16 | this.lastPosition = position; 17 | this.lastTimestamp = timestamp; 18 | } 19 | 20 | estimateSpeed() { 21 | const finalTrend = this.history.slice(-3); 22 | const sum = finalTrend.reduce((r, v) => r + v, 0); 23 | return sum / finalTrend.length; 24 | } 25 | 26 | reset() { 27 | this.history = []; 28 | this.lastPosition = undefined; 29 | this.lastTimestamp = undefined; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/interface.js: -------------------------------------------------------------------------------- 1 | const XDate = require('xdate'); 2 | 3 | function padNumber(n) { 4 | if (n < 10) { 5 | return '0' + n; 6 | } 7 | return n; 8 | } 9 | 10 | function xdateToData(xdate) { 11 | const dateString = xdate.toString('yyyy-MM-dd'); 12 | return { 13 | year: xdate.getFullYear(), 14 | month: xdate.getMonth() + 1, 15 | day: xdate.getDate(), 16 | weekDay: xdate.getDay(), 17 | timestamp: XDate(dateString, true).getTime(), 18 | dateString: dateString 19 | }; 20 | } 21 | 22 | function parseDate(d) { 23 | if (!d) { 24 | return; 25 | } else if (d.timestamp) { // conventional data timestamp 26 | return XDate(d.timestamp, true); 27 | } else if (d instanceof XDate) { // xdate 28 | return XDate(d.toString('yyyy-MM-dd'), true); 29 | } else if (d.getTime) { // javascript date 30 | const dateString = d.getFullYear() + '-' + padNumber((d.getMonth() + 1)) + '-' + padNumber(d.getDate()); 31 | return XDate(dateString, true); 32 | } else if (d.year) { 33 | const dateString = d.year + '-' + padNumber(d.month) + '-' + padNumber(d.day); 34 | return XDate(dateString, true); 35 | } else if (d) { // timestamp nuber or date formatted as string 36 | return XDate(d, true); 37 | } 38 | } 39 | 40 | module.exports = { 41 | xdateToData, 42 | parseDate 43 | }; 44 | 45 | -------------------------------------------------------------------------------- /src/interface.spec.js: -------------------------------------------------------------------------------- 1 | const iface = require('./interface'); 2 | const XDate = require('xdate'); 3 | 4 | describe('calendar interface', () => { 5 | describe('input', () => { 6 | it('should return undefined if date is undefined', () => { 7 | const date = iface.parseDate(); 8 | expect(date).toBe(undefined); 9 | }); 10 | 11 | it('should accept UTC timestamp as argument', () => { 12 | const date = iface.parseDate(1479832134398); 13 | expect(date.getTime()).toEqual(1479832134398); 14 | expect(date.getTimezoneOffset()).toEqual(0); 15 | }); 16 | 17 | it('should accept datestring as argument', () => { 18 | const date = iface.parseDate('2012-03-16'); 19 | expect(date.toString('yyyy-MM-dd')).toEqual('2012-03-16'); 20 | expect(date.getTimezoneOffset()).toEqual(0); 21 | }); 22 | 23 | it('should expect object with UTC timestamp as argument', () => { 24 | const date = iface.parseDate({timestamp: 1479832134398}); 25 | expect(date.getTime()).toEqual(1479832134398); 26 | expect(date.getTimezoneOffset()).toEqual(0); 27 | }); 28 | 29 | it('should accept XDate as argument', () => { 30 | const testDate = XDate('2016-11-22 00:00:00+3'); 31 | expect(testDate.toISOString()).toEqual('2016-11-21T21:00:00Z'); 32 | const time = 1479772800000; 33 | expect(XDate(time, true).toISOString()).toEqual('2016-11-22T00:00:00Z'); 34 | }); 35 | 36 | it('should accept Date as argument', () => { 37 | const testDate = new Date(2015, 5, 5, 12, 0); 38 | const date = iface.parseDate(testDate); 39 | expect(date.toString('yyyy-MM-dd')).toEqual('2015-06-05'); 40 | }); 41 | 42 | it('should accept data as argument', () => { 43 | const testDate = { 44 | year: 2015, 45 | month: 5, 46 | day: 6 47 | }; 48 | const date = iface.parseDate(testDate); 49 | expect(date.toString('yyyy-MM-dd')).toEqual('2015-05-06'); 50 | }); 51 | }); 52 | 53 | describe('output', () => { 54 | it('should convert xdate to data', () => { 55 | const time = 1479772800000; 56 | const testDate = XDate(time, true); 57 | expect((testDate).toISOString()).toEqual('2016-11-22T00:00:00Z'); 58 | const data = iface.xdateToData(testDate); 59 | expect(data).toEqual({ 60 | year: 2016, 61 | month: 11, 62 | day: 22, 63 | weekDay: 2, 64 | timestamp: 1479772800000, 65 | dateString: '2016-11-22' 66 | }); 67 | }); 68 | }); 69 | }); 70 | -------------------------------------------------------------------------------- /src/style.js: -------------------------------------------------------------------------------- 1 | import {Platform} from 'react-native'; 2 | 3 | export const foregroundColor = '#ffffff'; 4 | export const backgroundColor = '#f4f4f4'; 5 | export const separatorColor = '#e8e9ec'; 6 | 7 | export const processedColor = '#a7e0a3'; 8 | export const processingColor = '#ffce5c'; 9 | export const failedColor = 'rgba(246, 126, 126,1)'; 10 | 11 | export const textDefaultColor = '#2d4150'; 12 | export const textColor = '#43515c'; 13 | export const textLinkColor = '#00adf5'; 14 | export const textSecondaryColor = '#7a92a5'; 15 | 16 | export const textDayFontFamily = 'System'; 17 | export const textMonthFontFamily = 'System'; 18 | export const textDayHeaderFontFamily = 'System'; 19 | 20 | export const textMonthFontWeight = '300'; 21 | 22 | export const textDayFontSize = 16; 23 | export const textMonthFontSize = 16; 24 | export const textDayHeaderFontSize = 13; 25 | 26 | export const calendarBackground = foregroundColor; 27 | export const textSectionTitleColor = '#b6c1cd'; 28 | export const selectedDayBackgroundColor = textLinkColor; 29 | export const selectedDayTextColor = foregroundColor; 30 | export const todayBackgroundColor = undefined; 31 | export const todayTextColor = textLinkColor; 32 | export const dayTextColor = textDefaultColor; 33 | export const textDisabledColor = '#d9e1e8'; 34 | export const dotColor = textLinkColor; 35 | export const selectedDotColor = foregroundColor; 36 | export const arrowColor = textLinkColor; 37 | export const monthTextColor = textDefaultColor; 38 | export const agendaDayTextColor = '#7a92a5'; 39 | export const agendaDayNumColor = '#7a92a5'; 40 | export const agendaTodayColor = textLinkColor; 41 | export const agendaKnobColor = Platform.OS === 'ios' ? '#f2F4f5' : '#4ac4f7'; 42 | -------------------------------------------------------------------------------- /src/testIDs.js: -------------------------------------------------------------------------------- 1 | const PREFIX = 'native.calendar'; 2 | 3 | module.exports = { 4 | CHANGE_MONTH_LEFT_ARROW: `${PREFIX}.CHANGE_MONTH_LEFT_ARROW`, 5 | CHANGE_MONTH_RIGHT_ARROW: `${PREFIX}.CHANGE_MONTH_RIGHT_ARROW` 6 | }; --------------------------------------------------------------------------------