├── .babelrc ├── .buckconfig ├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .flowconfig ├── .gitattributes ├── .gitignore ├── .npmignore ├── .travis.yml ├── .watchmanconfig ├── CHANGELOG.md ├── LICENSE ├── README.md ├── android ├── app │ ├── BUCK │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── reactnativeuixg │ │ │ ├── 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 ├── components ├── Accordion │ ├── .npmignore │ ├── Accordion.js │ ├── Collapse.js │ ├── LICENSE │ ├── README.md │ ├── __tests__ │ │ └── test.js │ ├── example │ │ └── index.js │ └── package.json ├── ActionSheet │ ├── .npmignore │ ├── LICENSE │ ├── README.md │ ├── __tests__ │ │ └── ActionSheet.test.js │ ├── actionSheetAndroid.js │ ├── actionSheetIOS.js │ ├── example │ │ └── index.js │ ├── index.js │ └── package.json ├── Button │ ├── .npmignore │ ├── Button.js │ ├── ButtonInfo.js │ ├── ButtonStyle.js │ ├── LICENSE │ ├── README.md │ ├── __tests__ │ │ └── Button.test.js │ ├── example │ │ └── index.js │ ├── judge.js │ └── package.json ├── CalendarSelect │ ├── .npmignore │ ├── CalendarStyle.js │ ├── Day │ │ ├── index.js │ │ └── style.js │ ├── LICENSE │ ├── Month │ │ ├── index.js │ │ └── style.js │ ├── MonthList.js │ ├── README.md │ ├── __tests__ │ │ └── Calendar.test.js │ ├── example │ │ └── index.js │ ├── index.js │ └── package.json ├── Confirm │ ├── .npmignore │ ├── Confirm.js │ ├── ConfirmStyle.js │ ├── LICENSE │ ├── README.md │ ├── __tests__ │ │ └── Confirm.test.js │ ├── example │ │ └── index.js │ └── package.json ├── DatePicker │ ├── .npmignore │ ├── CHANGELOG.md │ ├── Datepicker.js │ ├── LICENSE │ ├── README.md │ ├── __tests__ │ │ └── Datepicker.test.js │ ├── date_icon.png │ ├── example │ │ ├── google_calendar.png │ │ └── index.js │ ├── package.json │ └── style.js ├── Drawer │ ├── .npmignore │ ├── Animation.js │ ├── LICENSE │ ├── README.md │ ├── __tests__ │ │ └── Drawer.test.js │ ├── example │ │ └── index.js │ ├── index.js │ └── package.json ├── Grading │ ├── .npmignore │ ├── GradingConstants.js │ ├── GradingModal.js │ ├── GradingModalStyle.js │ ├── GradingStyle.js │ ├── LICENSE │ ├── README.md │ ├── __tests__ │ │ ├── Grading.test.js │ │ └── __snapshots__ │ │ │ └── Grading.test.js.snap │ ├── example │ │ └── index.js │ └── index.js ├── Input │ ├── .npmignore │ ├── Input.js │ ├── InputStyle.js │ ├── LICENSE │ ├── README.md │ ├── __tests__ │ │ ├── Input.test.js │ │ └── __snapshots__ │ │ │ └── Input.test.js.snap │ ├── example │ │ └── index.js │ └── package.json ├── LabelSelect │ ├── .npmignore │ ├── LICENSE │ ├── LabelSelectStyle.js │ ├── README.md │ ├── __tests__ │ │ ├── LabelSelect.test.js │ │ ├── __mock__ │ │ │ └── mock.json │ │ └── __snapshots__ │ │ │ └── LabelSelect.test.js.snap │ ├── example │ │ └── index.js │ ├── index.js │ └── package.json ├── Link │ ├── .npmignore │ ├── LICENSE │ ├── Link.js │ ├── LinkStyle.js │ ├── README.md │ ├── __tests__ │ │ └── Link.test.js │ ├── example │ │ └── index.js │ └── package.json ├── PressMenu │ ├── .npmignore │ ├── LICENSE │ ├── README.md │ ├── __tests__ │ │ └── test.js │ ├── example │ │ └── index.js │ ├── index.js │ └── package.json ├── Tab │ ├── .npmignore │ ├── LICENSE │ ├── README.md │ ├── Tab.js │ ├── TabStyle.js │ ├── __tests__ │ │ └── Tab.test.js │ ├── example │ │ └── index.js │ └── package.json ├── ZoomImage │ ├── .npmignore │ ├── Animation.js │ ├── LICENSE │ ├── README.md │ ├── __tests__ │ │ └── test.js │ ├── example │ │ └── index.js │ ├── index.js │ └── package.json └── package.json ├── example ├── Home.js ├── HomeStyle.js ├── registerScreens.js └── res │ ├── logo.png │ └── right.png ├── index.android.js ├── index.ios.js ├── index.js ├── ios ├── reactNativeUiXg-tvOS │ └── Info.plist ├── reactNativeUiXg-tvOSTests │ └── Info.plist ├── reactNativeUiXg.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ ├── reactNativeUiXg-tvOS.xcscheme │ │ └── reactNativeUiXg.xcscheme ├── reactNativeUiXg │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Base.lproj │ │ └── LaunchScreen.xib │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Info.plist │ └── main.m └── reactNativeUiXgTests │ ├── Info.plist │ └── reactNativeUiXgTests.m ├── package.json └── tools ├── checkGit.js ├── component ├── .npmignore ├── LICENSE ├── README.md ├── __tests__ │ └── test.js ├── example │ └── index.js ├── index.js └── package.json └── new.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["react-native"] 3 | } -------------------------------------------------------------------------------- /.buckconfig: -------------------------------------------------------------------------------- 1 | 2 | [android] 3 | target = Google Inc.:Google APIs:23 4 | 5 | [maven_repositories] 6 | central = https://repo1.maven.org/maven2 7 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | android/ 2 | ios/ 3 | coverage/ 4 | node_modules/ 5 | tools/ 6 | -------------------------------------------------------------------------------- /.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 | module.system=haste 26 | 27 | experimental.strict_type_args=true 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\\.\\(3[0-7]\\|[1-2][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\) 38 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(3[0-7]\\|1[0-9]\\|[1-2][0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+ 39 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy 40 | 41 | unsafe.enable_getters_and_setters=true 42 | 43 | [version] 44 | ^0.37.0 45 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | -------------------------------------------------------------------------------- /.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 | .idea 28 | .gradle 29 | local.properties 30 | *.iml 31 | 32 | # node.js 33 | # 34 | node_modules/ 35 | npm-debug.log 36 | yarn-error.log 37 | 38 | # BUCK 39 | buck-out/ 40 | \.buckd/ 41 | android/app/libs 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 | 55 | coverage/ 56 | 57 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | example/ 2 | __tests__/ 3 | .* 4 | components/ 5 | coverage/ 6 | index.android.js 7 | index.ios.js 8 | android/ 9 | ios/ 10 | tools/ 11 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | sudo: true 3 | node_js: 4 | - "4.4" 5 | cache: 6 | directories: 7 | before_install: 8 | - npm i -g npm@3 9 | - npm --version 10 | script: 11 | - npm test -- -u 12 | after_script: 13 | - npm run coverage 14 | -------------------------------------------------------------------------------- /.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | ## 0.0.2 (2017-03-20) 3 | 4 | 5 | ### Bug Fixes 6 | 7 | * **package.json:** change test ([81bee15](https://github.com/xgfe/react-native-ui-xg/commit/81bee15)) 8 | 9 | 10 | ### Features 11 | 12 | * **Button:** add Button Component ([c2a9f3c](https://github.com/xgfe/react-native-ui-xg/commit/c2a9f3c)) 13 | * **Confirm:** add Confirm component ([1882fd5](https://github.com/xgfe/react-native-ui-xg/commit/1882fd5)) 14 | * **Drawer / LabelSelect / Grading:** add three new components ([4dfdfcb](https://github.com/xgfe/react-native-ui-xg/commit/4dfdfcb)) 15 | * **GLOBAL:** change readme ([e7e32c1](https://github.com/xgfe/react-native-ui-xg/commit/e7e32c1)) 16 | * **Input:** add Input component ([77f6b75](https://github.com/xgfe/react-native-ui-xg/commit/77f6b75)) 17 | * **Input:** Add Real Input ([e020d69](https://github.com/xgfe/react-native-ui-xg/commit/e020d69)) 18 | * **Link:** add Link component ([e3ea982](https://github.com/xgfe/react-native-ui-xg/commit/e3ea982)) 19 | * **Tab:** add Tab component ([b300a96](https://github.com/xgfe/react-native-ui-xg/commit/b300a96)) 20 | * **tools:** add new command to generate boilerplate ([734a8e9](https://github.com/xgfe/react-native-ui-xg/commit/734a8e9)) 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 鲜果FE 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, 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, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-native-ui-xg [![Build Status](https://travis-ci.org/xgfe/react-native-ui-xg.svg?branch=master)](https://travis-ci.org/xgfe/react-native-ui-xg) [![Coverage Status](https://coveralls.io/repos/github/xgfe/react-native-ui-xg/badge.svg?branch=master)](https://coveralls.io/github/xgfe/react-native-ui-xg?branch=master) 2 | 3 | A suit of cross platform React Native ui kit. 4 | 5 | ![image](https://raw.githubusercontent.com/lulutia/images/master/react-native-components/Screen-Capture-44.gif) 6 | 7 | ## Install 8 | 9 | ```bash 10 | npm install react-native-ui-xg --save 11 | ``` 12 | 13 | ## Usage 14 | 15 | ### for the whole 16 | ```js 17 | import { 18 | Tab, 19 | Link, 20 | Input, 21 | Button, 22 | Grading, 23 | Confirm, 24 | Accordion, 25 | ZoomImage, 26 | DrawerMenu, 27 | DatePicker, 28 | ActionSheet, 29 | LabelSelect, 30 | CalendarSelect 31 | } from 'react-native-ui-xg'; 32 | ``` 33 | ### for one by one 34 | 35 | ```bash 36 | 37 | npm install react-native-tab-xg --save 38 | npm install react-native-link-xg --save 39 | npm install react-native-buttons --save 40 | npm install react-native-grading --save 41 | npm install react-native-confirm --save 42 | npm install react-native-input-xg --save 43 | npm install react-native-zoom-image --save 44 | npm install react-native-datepicker --save 45 | npm install react-native-drawer-menu --save 46 | npm install react-native-label-select --save 47 | npm install react-native-accordion-xg --save 48 | npm install react-native-action-sheet-xg --save 49 | npm install react-native-calendar-select --save 50 | ``` 51 | 52 | ## Components 53 | 54 | * [Tab](https://github.com/xgfe/react-native-ui-xg/blob/master/components/Tab/README.md) 55 | * [Link](https://github.com/xgfe/react-native-ui-xg/blob/master/components/Link/README.md) 56 | * [Input](https://github.com/xgfe/react-native-ui-xg/blob/master/components/Input/README.md) 57 | * [Button](https://github.com/xgfe/react-native-ui-xg/blob/master/components/Button/README.md) 58 | * [Grading](https://github.com/xgfe/react-native-ui-xg/blob/master/components/Grading/README.md) 59 | * [Confirm](https://github.com/xgfe/react-native-ui-xg/blob/master/components/Confirm/README.md) 60 | * [Accordion](https://github.com/xgfe/react-native-ui-xg/blob/master/components/Accordion/README.md) 61 | * [ZoomImage](https://github.com/xgfe/react-native-ui-xg/blob/master/components/ZoomImage/README.md) 62 | * [DatePicker](https://github.com/xgfe/react-native-ui-xg/tree/master/components/DatePicker) 63 | * [StyleSheet](https://github.com/xgfe/react-native-ui-xg/blob/master/components/StyleSheet/README.md) 64 | * [DrawerMenu](https://github.com/xgfe/react-native-ui-xg/blob/master/components/Drawer/README.md) 65 | * [LabelSelect](https://github.com/xgfe/react-native-ui-xg/blob/master/components/LabelSelect/README.md) 66 | * [ActionSheet](https://github.com/xgfe/react-native-ui-xg/blob/master/components/ActionSheet/README.md) 67 | * [ActionSheet](https://github.com/xgfe/react-native-ui-xg/blob/master/components/CalendarSelect/README.md) 68 | 69 | ## Example 70 | 71 | * git clone https://github.com/xgfe/react-native-ui-xg.git 72 | * cd react-native-ui-xg && npm install 73 | * react-native run-android 74 | -------------------------------------------------------------------------------- /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.reactnativeuixg", 49 | ) 50 | 51 | android_resource( 52 | name = "res", 53 | package = "com.reactnativeuixg", 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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/reactnativeuixg/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.reactnativeuixg; 2 | 3 | import com.reactnativenavigation.controllers.SplashActivity; 4 | 5 | public class MainActivity extends SplashActivity { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/reactnativeuixg/MainApplication.java: -------------------------------------------------------------------------------- 1 | package com.reactnativeuixg; 2 | 3 | import android.support.annotation.NonNull; 4 | import com.facebook.react.ReactPackage; 5 | import com.reactnativenavigation.NavigationApplication; 6 | 7 | import java.util.List; 8 | 9 | public class MainApplication extends NavigationApplication { 10 | 11 | @Override 12 | public boolean isDebug() { 13 | return BuildConfig.DEBUG; 14 | } 15 | 16 | @NonNull 17 | @Override 18 | public List createAdditionalReactPackages() { 19 | // Add the packages you require here. 20 | // No need to add RnnPackage and MainReactPackage 21 | return null; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xgfe/react-native-ui-xg/59f111fdb0fcb416948212f941d2fc2f486d4adb/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xgfe/react-native-ui-xg/59f111fdb0fcb416948212f941d2fc2f486d4adb/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xgfe/react-native-ui-xg/59f111fdb0fcb416948212f941d2fc2f486d4adb/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xgfe/react-native-ui-xg/59f111fdb0fcb416948212f941d2fc2f486d4adb/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | reactNativeUiXg 3 | 4 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xgfe/react-native-ui-xg/59f111fdb0fcb416948212f941d2fc2f486d4adb/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /android/keystores/BUCK: -------------------------------------------------------------------------------- 1 | keystore( 2 | name = "debug", 3 | properties = "debug.keystore.properties", 4 | store = "debug.keystore", 5 | visibility = [ 6 | "PUBLIC", 7 | ], 8 | ) 9 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'reactNativeUiXg' 2 | 3 | include ':app' 4 | 5 | include ':react-native-navigation' 6 | project(':react-native-navigation').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-navigation/android/app/') 7 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "reactNativeUiXg", 3 | "displayName": "reactNativeUiXg" 4 | } 5 | -------------------------------------------------------------------------------- /components/Accordion/.npmignore: -------------------------------------------------------------------------------- 1 | example 2 | __tests__ 3 | .* 4 | -------------------------------------------------------------------------------- /components/Accordion/Accordion.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by lulutia on 2017-04-13. 3 | */ 4 | 5 | import React, {PropTypes, Component} from 'react'; 6 | import { 7 | StyleSheet, 8 | View, 9 | TouchableHighlight 10 | } from 'react-native'; 11 | 12 | import Collapse from './Collapse'; 13 | 14 | export default class Accordion extends Component { 15 | constructor(props) { 16 | super(props); 17 | this.state = { 18 | activeItem: undefined 19 | }; 20 | } 21 | 22 | _toggle(index) { 23 | let oldItem = this.state.activeItem; 24 | if (oldItem === index) { 25 | this.setState({activeItem: undefined}); 26 | } else { 27 | this.setState({activeItem: index}); 28 | } 29 | } 30 | render() { 31 | const { 32 | items, 33 | headerRender, 34 | contentRender, 35 | headerName, 36 | contentName, 37 | maxHeight, 38 | duration, 39 | backgroundColor 40 | } = this.props; 41 | return ( 42 | 43 | {items.map((item, index) => { 44 | return ( 45 | 46 | {this._toggle(index);}}> 50 | {headerRender(item[headerName])} 51 | 52 | 59 | 60 | ); 61 | })} 62 | 63 | ); 64 | } 65 | } 66 | 67 | 68 | const styles = StyleSheet.create({ 69 | container: { 70 | flex: 1 71 | }, 72 | header: { 73 | borderTopWidth: 1, 74 | borderColor: '#eee' 75 | }, 76 | headerBorder: { 77 | borderBottomWidth: 1 78 | }, 79 | collapseContainer: { 80 | paddingTop: 0 81 | }, 82 | collapseItem: { 83 | paddingBottom: 0 84 | } 85 | }); 86 | 87 | Accordion.defaultProps = { 88 | items: [], 89 | duration: 500 90 | }; 91 | -------------------------------------------------------------------------------- /components/Accordion/Collapse.js: -------------------------------------------------------------------------------- 1 | import React, {PropTypes, Component} from 'react'; 2 | import { 3 | StyleSheet, 4 | Animated, 5 | ScrollView 6 | } from 'react-native'; 7 | 8 | 9 | export default class Collapse extends Component { 10 | static defaultProps = { 11 | height: 0 12 | } 13 | 14 | constructor(props) { 15 | super(props); 16 | this.state = { 17 | height: new Animated.Value(this.props.height) 18 | }; 19 | this.getContentHeight = this.getContentHeight.bind(this); 20 | this.handleHeight = this.handleHeight.bind(this); 21 | 22 | this.contentInit = false; 23 | this.contentHeight = 0; 24 | } 25 | 26 | getContentHeight(event) { 27 | if (!this.contentInit) { 28 | this.props.maxHeight ? this.contentHeight = Math.min(this.props.maxHeight, event.nativeEvent.layout.height) : this.contentHeight = event.nativeEvent.layout.height; 29 | this.contentInit = true; 30 | this.forceUpdate(); 31 | } 32 | } 33 | 34 | handleHeight() { 35 | if (this.props.collapse) { 36 | Animated.timing( 37 | this.state.height, 38 | {toValue: 0, 39 | duration: this.props.duration} 40 | ).start(); 41 | } else { 42 | Animated.timing( 43 | this.state.height, 44 | {toValue: this.contentHeight, 45 | duration: this.props.duration} 46 | ).start(); 47 | } 48 | } 49 | render() { 50 | if (this.contentInit) { 51 | this.handleHeight(); 52 | } 53 | return ( 54 | 55 | {this.getContentHeight(event);}}> 56 | {this.props.content} 57 | 58 | 59 | ); 60 | } 61 | } 62 | 63 | const styles = StyleSheet.create({ 64 | container: { 65 | flex: 1 66 | }, 67 | collapseContainer: { 68 | paddingTop: 0 69 | }, 70 | collapseItem: { 71 | paddingBottom: 0 72 | } 73 | }); 74 | -------------------------------------------------------------------------------- /components/Accordion/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 鲜果FE 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, 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, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /components/Accordion/README.md: -------------------------------------------------------------------------------- 1 | ## react-native-action-sheet 2 | 3 | Accordion component for React Native Application (ios / android) 4 | 5 | 6 | ### Examples 7 | accordion 8 | ![image](https://raw.githubusercontent.com/lulutia/images/master/react-native-components/Screen-Capture-55.gif) 9 | 10 | ### Usage 11 | 12 | **install from npm** 13 | 14 | ``` shell 15 | npm install --save react-native-accordion-xg 16 | ``` 17 | 18 | **import in project** 19 | 20 | ``` js 21 | import Accordion from 'react-native-accordion-xg'; 22 | ``` 23 | 24 | ## Properties 25 | | Prop | Default | Type | Description | 26 | | :------------ |:---------------:| :---------------:| :-----| 27 | | item | - | `array` | the data of the accordion | 28 | | headerRender | - | `function` | the way to render the header | 29 | | contentRender | - | 'function' | the way to render the content| 30 | | headerName | - | 'string' | the key of the item that indicates the data for the header| 31 | | contentName | - | 'string' | the key of the item that indicates the data for the content| 32 | | maxHeight | - | 'number' | the max height of the content to show| 33 | | duration | - | 'number' | the duration of the hidden content to show| 34 | | backgroundColor | - | 'number' | the backgroundColoe of the content when bounced in ios | 35 | 36 | 37 | LICENSE MIT 38 | -------------------------------------------------------------------------------- /components/Accordion/__tests__/test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by lulutia on 2017-04-13. 3 | */ 4 | 5 | /* eslint-disable */ 6 | 7 | import {jsdom} from 'jsdom'; 8 | global.document = jsdom(''); 9 | global.window = document.defaultView; 10 | import { 11 | View, 12 | ScrollView, 13 | Text 14 | } from 'react-native'; 15 | import React from 'react'; 16 | import {shallow, mount} from 'enzyme'; 17 | import renderer from 'react-test-renderer'; 18 | 19 | import Accordion from '../Accordion'; 20 | import Collapse from '../Collapse'; 21 | 22 | console.error = function () {}; 23 | 24 | describe('test node', () => { 25 | it('check', () => { 26 | const items = [ 27 | { 28 | name: "Gone with the Wind", 29 | description: "Gone with the Wind is a 1939 American epic historical romance film adapted from Margaret Mitchell's 1936 novel Gone with the Wind. It was produced by David O. Selznick of Selznick International Pictures and directed by Victor Fleming." 30 | }, 31 | { 32 | name: "The Godfather", 33 | description: "The Godfather is a 1972 American crime film directed by Francis Ford Coppola and produced by Albert S. Ruddy, based on Mario Puzo's best-selling novel of the same name." 34 | }, 35 | { 36 | name: "tesr", 37 | description: 'test' 38 | } 39 | ]; 40 | 41 | function renderHeader(info) { 42 | return ( 43 | 44 | {info} 45 | 46 | ); 47 | } 48 | 49 | function renderContent(info) { 50 | return ( 51 | 52 | {info} 53 | 54 | ); 55 | } 56 | 57 | const wrapper = shallow(); 63 | let instance = wrapper.instance(); 64 | expect(wrapper.state('activeItem')).toEqual(undefined); 65 | instance._toggle(2); 66 | expect(wrapper.state('activeItem')).toEqual(2); 67 | instance._toggle(2); 68 | expect(wrapper.state('activeItem')).toEqual(undefined); 69 | }); 70 | }); 71 | 72 | describe('test collapse', ()=>{ 73 | it ('check basic', ()=>{ 74 | const wrapper = mount(); 75 | const wrapper1 = shallow(); 76 | let instance = wrapper1.instance(); 77 | expect(instance.contentInit).toEqual(false); 78 | instance.getContentHeight({nativeEvent:{layout:{height: 80}}}); 79 | expect(instance.contentInit).toEqual(true); 80 | }) 81 | }) 82 | 83 | -------------------------------------------------------------------------------- /components/Accordion/example/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by lulutia on 2017-04-13. 3 | */ 4 | 5 | import React, {Component} from 'react'; 6 | import { 7 | StyleSheet, 8 | View, 9 | Text 10 | } from 'react-native'; 11 | 12 | import Accordion from '../Accordion'; 13 | 14 | const items = [ 15 | { 16 | name: 'HOME', 17 | description: "Gone with the Wind is a 1939 American epic historical romance film adapted from Margaret Mitchell's 1936 novel Gone with the Wind. It was produced by David O. Selznick of Selznick International Pictures and directed by Victor Fleming." 18 | }, 19 | { 20 | name: 'PRODUCT', 21 | description: "The Godfather is a 1972 American crime film directed by Francis Ford Coppola and produced by Albert S. Ruddy, based on Mario Puzo's best-selling novel of the same name." 22 | }, 23 | { 24 | name: 'SETTINGS', 25 | description: 'just for test' 26 | } 27 | ]; 28 | 29 | export default class AccordionExample extends Component { 30 | 31 | renderHeader(info) { 32 | return ( 33 | 34 | {info} 35 | 36 | ); 37 | } 38 | 39 | renderContent(info) { 40 | return ( 41 | 42 | {info} 43 | 44 | ); 45 | } 46 | render() { 47 | return ( 48 | 49 | 60 | 61 | ); 62 | } 63 | } 64 | 65 | const styles = StyleSheet.create({ 66 | example: { 67 | flex: 1, 68 | justifyContent: 'center', 69 | paddingTop: 40, 70 | backgroundColor: '#f1f1f1' 71 | }, 72 | accordion: { 73 | borderTopWidth: 1, 74 | borderTopColor: '#666' 75 | }, 76 | content: { 77 | padding: 10, 78 | backgroundColor: '#fff' 79 | }, 80 | header: { 81 | padding: 10, 82 | backgroundColor: '#fff' 83 | }, 84 | headerText: { 85 | }, 86 | contentText: { 87 | } 88 | }); 89 | -------------------------------------------------------------------------------- /components/Accordion/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-accordion-xg", 3 | "version": "0.0.1", 4 | "description": "", 5 | "main": "./Accordion.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/xgfe/react-native-ui-xg.git" 9 | }, 10 | "keywords": [ 11 | "react-native", 12 | "xgfe", 13 | "react-native-accordion", 14 | "accordion" 15 | ], 16 | "author": "xgfe", 17 | "license": "MIT", 18 | "bugs": { 19 | "url": "https://github.com/xgfe/react-native-ui-xg/issues" 20 | }, 21 | "homepage": "https://github.com/xgfe/react-native-ui-xg#readme" 22 | } 23 | -------------------------------------------------------------------------------- /components/ActionSheet/.npmignore: -------------------------------------------------------------------------------- 1 | example 2 | __tests__ 3 | .* 4 | -------------------------------------------------------------------------------- /components/ActionSheet/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 鲜果FE 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, 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, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /components/ActionSheet/README.md: -------------------------------------------------------------------------------- 1 | ## react-native-action-sheet 2 | 3 | ActionSheet component for React Native Application (ios / android) 4 | 5 | 6 | ### Examples 7 | actionSheet 8 | ![image](https://raw.githubusercontent.com/lulutia/images/master/react-native-components/Screen-Capture-53.gif) 9 | 10 | ### Usage 11 | 12 | **install from npm** 13 | 14 | ``` shell 15 | npm install --save react-native-action-sheet-xg 16 | ``` 17 | 18 | **import in project** 19 | 20 | ``` js 21 | import ActionSheet from 'react-native-action-sheet-xg'; 22 | ``` 23 | 24 | ## Properties 25 | | Prop | Default | Type | Description | 26 | | :------------ |:---------------:| :---------------:| :-----| 27 | | title | - | `string` | the title of the action sheet | 28 | | message | - | `string | the message of the title | 29 | | options | - | 'array' | the item of the action sheet| 30 | | cancelButtonIndex | - | 'number' | the index of the cancel button of the options| 31 | | destructiveButtonIndex | - | 'number' | the index of the destructiove button of the options| 32 | | ref | - | 'string' | the ref name of the component| 33 | | callback | - | 'function' | the callback of the chose| 34 | 35 | 36 | LICENSE MIT 37 | -------------------------------------------------------------------------------- /components/ActionSheet/__tests__/ActionSheet.test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by lulutia on 2017-03-31. 3 | */ 4 | 5 | /* eslint-disable */ 6 | import {jsdom} from 'jsdom'; 7 | global.document = jsdom(''); 8 | global.window = document.defaultView; 9 | global.cancelAnimationFrame = () => {}; 10 | import { 11 | View, 12 | Modal, 13 | Platform, 14 | TouchableHighlight, 15 | ActionSheetIOS 16 | } from 'react-native'; 17 | import React from 'react'; 18 | import {shallow, mount} from 'enzyme'; 19 | import renderer from 'react-test-renderer'; 20 | 21 | import ActionSheet from '../actionSheetAndroid'; 22 | import ActionsheetIOS from '../actionSheetIOS'; 23 | ActionSheetIOS.showActionSheetWithOptions = () => {}; 24 | 25 | 26 | describe('test node', () => { 27 | it('check node number', () => { 28 | const wrapper = mount(); 29 | expect(wrapper.find(Modal).length).toEqual(1); 30 | const wrapper1 = mount(); 31 | expect(wrapper1.find(Modal).length).toEqual(0); 32 | }) 33 | }) 34 | 35 | describe('test begin', () => { 36 | it('check show', () => { 37 | let BUTTONS = [ 38 | 'Option 0', 39 | 'Option 1', 40 | 'Option 2', 41 | 'Delete', 42 | 'Cancel' 43 | ]; 44 | 45 | let DESTRUCTIVE_INDEX = 3; 46 | let CANCEL_INDEX = 4; 47 | let temp = false; 48 | const wrapper = shallow( 49 | { 57 | temp = true; 58 | }} 59 | /> 60 | ); 61 | const wrapper1 = shallow( 62 | { 70 | temp = true; 71 | }} 72 | /> 73 | ); 74 | let instance = wrapper.instance(); 75 | let instance1 = wrapper.instance(); 76 | let instance2 = wrapper1.instance(); 77 | 78 | expect(wrapper.state('modalVisible')).toEqual(false); 79 | instance.show(); 80 | expect(wrapper.state('modalVisible')).toEqual(true); 81 | wrapper.find(TouchableHighlight).first().simulate('press'); 82 | instance1.finishChose(2); 83 | expect(temp).toEqual(true); 84 | 85 | instance2.show(); 86 | }) 87 | }) 88 | 89 | 90 | -------------------------------------------------------------------------------- /components/ActionSheet/actionSheetIOS.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by lulutia on 2017-03-31. 3 | */ 4 | 5 | import React, {Component} from 'react'; 6 | import { 7 | StyleSheet, 8 | View, 9 | ActionSheetIOS 10 | } from 'react-native'; 11 | 12 | export default class ActionSheetNewIOS extends Component { 13 | 14 | constructor(props) { 15 | super(props); 16 | } 17 | 18 | show() { 19 | ActionSheetIOS.showActionSheetWithOptions({ 20 | options: this.props.options, 21 | cancelButtonIndex: this.props.cancelButtonIndex, 22 | destructiveButtonIndex: this.props.destructiveButtonIndex, 23 | tintColor: this.props.tintColor, 24 | title: this.props.title, 25 | message: this.props.message 26 | }, this.props.callback); 27 | } 28 | render() { 29 | return null; 30 | } 31 | } 32 | 33 | ActionSheetNewIOS.defaultProps = { 34 | options: {}, 35 | callback: () => {}, 36 | failCallback: () => {}, 37 | successCallback: () => {} 38 | }; 39 | 40 | ActionSheetNewIOS.propTypes = { 41 | ...ActionSheetIOS.propTypes 42 | }; 43 | 44 | -------------------------------------------------------------------------------- /components/ActionSheet/example/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by lulutia on 2017-03-31. 3 | */ 4 | 5 | import React, {Component} from 'react'; 6 | import { 7 | StyleSheet, 8 | View, 9 | Text 10 | } from 'react-native'; 11 | import {Button} from '../../../'; 12 | 13 | import ActionSheet from '../index'; 14 | 15 | let BUTTONS = [ 16 | 'Option 0', 17 | 'Option 1', 18 | 'Option 2', 19 | 'Delete', 20 | 'Cancel' 21 | ]; 22 | 23 | let DESTRUCTIVE_INDEX = 3; 24 | let CANCEL_INDEX = 4; 25 | 26 | export default class ActionSheetExample extends Component { 27 | constructor(props) { 28 | super(props); 29 | this.state = { 30 | clicked: 'none', 31 | text: '' 32 | }; 33 | this.showActionSheet = this.showActionSheet.bind(this); 34 | } 35 | 36 | showActionSheet() { 37 | this.refs.action1.show(); 38 | } 39 | 40 | 41 | render() { 42 | 43 | return ( 44 | 45 | 46 | 47 | Clicked button: {this.state.clicked} 48 | 49 | { 57 | this.setState({clicked: BUTTONS[buttonIndex]}); 58 | }} 59 | ref = "action1" 60 | /> 61 | 62 | ); 63 | } 64 | } 65 | 66 | const styles = StyleSheet.create({ 67 | example: { 68 | flex: 1, 69 | justifyContent: 'center', 70 | alignItems: 'center' 71 | }, 72 | button: { 73 | marginBottom: 10, 74 | fontWeight: '500', 75 | backgroundColor: '#1194f6' 76 | }, 77 | container: { 78 | flex: 1, 79 | justifyContent: 'center', 80 | alignItems: 'center' 81 | }, 82 | welcome: { 83 | fontSize: 20, 84 | textAlign: 'center', 85 | margin: 10 86 | }, 87 | instructions: { 88 | textAlign: 'center', 89 | color: '#333333', 90 | marginBottom: 5 91 | } 92 | }); 93 | -------------------------------------------------------------------------------- /components/ActionSheet/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by lulutia on 2017-03-31. 3 | */ 4 | 5 | import { 6 | Platform 7 | } from 'react-native'; 8 | 9 | import ActionSheetAndroid from './actionSheetAndroid'; 10 | import ActionSheetNewIOS from './actionSheetIOS'; 11 | 12 | let ActionSheet = Platform.OS === 'android' ? ActionSheetAndroid : ActionSheetNewIOS; 13 | 14 | export default ActionSheet; 15 | 16 | -------------------------------------------------------------------------------- /components/ActionSheet/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-action-sheet-xg", 3 | "version": "0.0.1", 4 | "description": "react native ActionSheet component for both Android and IOS, useing pure JavaScript", 5 | "main": "Tab.js", 6 | "main": "./index.js", 7 | "repository": { 8 | "type": "git", 9 | "url": "git+https://github.com/xgfe/react-native-ui-xg.git" 10 | }, 11 | "keywords": [ 12 | "react-native", 13 | "xgfe", 14 | "actionSheet", 15 | "react-native-actionSheet", 16 | "react-native-action-sheet" 17 | ], 18 | "author": "xgfe", 19 | "license": "MIT", 20 | "bugs": { 21 | "url": "https://github.com/xgfe/react-native-ui-xg/issues" 22 | }, 23 | "homepage": "https://github.com/xgfe/react-native-ui-xg#readme", 24 | "dependencies": { 25 | "react-native-stylesheet-xg": "^1.1.0" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /components/Button/.npmignore: -------------------------------------------------------------------------------- 1 | example 2 | __tests__ 3 | .* 4 | -------------------------------------------------------------------------------- /components/Button/Button.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import { 3 | Text, 4 | TouchableHighlight, 5 | ActivityIndicator, 6 | TouchableNativeFeedback, 7 | View 8 | } from 'react-native'; 9 | import { 10 | ButtonType, 11 | ButtonOuter, 12 | BasicColor 13 | } from './ButtonStyle'; 14 | 15 | import {judgePlatformLevel} from './judge'; 16 | 17 | class Button extends Component { 18 | 19 | constructor(props) { 20 | super(props); 21 | this.state = {}; 22 | this.renderChildren = this._renderChildren.bind(this); 23 | } 24 | 25 | _renderChildren(size, color) { 26 | const { 27 | children = '', 28 | isLoading = false, 29 | disabled = false, 30 | loadingTitle = 'Loading', 31 | active = false 32 | } = this.props; 33 | let childrenNode = []; 34 | if (isLoading) { 35 | let loadingSize = size; 36 | if (loadingSize === 'default') {loadingSize = 'small';} 37 | return 38 | 42 | 46 | {loadingTitle} 47 | 48 | ; 49 | } else { 50 | React.Children.forEach(children, function (item) { 51 | if (React.isValidElement(item)) { 52 | childrenNode.push(item); 53 | } else if (typeof item === 'string' || item === 'number') { 54 | const node = ( 60 | {item} 61 | ); 62 | childrenNode.push(node); 63 | } 64 | }); 65 | return {childrenNode}; 66 | } 67 | } 68 | 69 | render() { 70 | const { 71 | theme = 'default', 72 | type = 'surface', 73 | size = 'default', 74 | disabled = false, 75 | isLoading = false, 76 | disableColor = '', 77 | activeColor = '', 78 | loadingColor = '', 79 | active = false 80 | } = this.props; 81 | let colorConfig = new BasicColor(theme, type, disableColor, activeColor, loadingColor); 82 | let handleProps = (!disabled && !isLoading) ? this.props : null; 83 | 84 | if (!judgePlatformLevel('TouchableNativeFeedback') || disabled || isLoading) { 85 | return ( 86 | 97 | {this._renderChildren(size, colorConfig)} 98 | 99 | ); 100 | } 101 | return ( 102 | 106 | 113 | {this._renderChildren(size, colorConfig)} 114 | 115 | 116 | ); 117 | } 118 | } 119 | 120 | Button.propTypes = { 121 | onPress: React.PropTypes.func.isRequired, 122 | disabled: React.PropTypes.bool, 123 | theme: React.PropTypes.string.isRequired, 124 | size: React.PropTypes.oneOf(['default', 'small', 'large']), 125 | type: React.PropTypes.oneOf(['ghost', 'surface']) 126 | }; 127 | 128 | export default Button; 129 | -------------------------------------------------------------------------------- /components/Button/ButtonInfo.js: -------------------------------------------------------------------------------- 1 | const BackgroundColors = { 2 | 3 | //背景颜色 4 | default: '#06C1AE', 5 | orange: '#FF9900', 6 | blue: '#06C1AE', 7 | red: '#EC5330', 8 | gray: '#D2D2D2' 9 | }; 10 | 11 | const ActiveColor = { 12 | orangeActive: '#D66500', 13 | defaultActive: '#049387', 14 | blueActive: '#049387', 15 | redActive: '#C23E1A', 16 | grayActive: '#8E8E8E' 17 | }; 18 | 19 | const DisableColor = { 20 | orangeDisable: '#FFD084', 21 | blueDisable: '#96E4DA', 22 | defaultDisable: '#96E4DA', 23 | redDisable: '#FDC1B5', 24 | grayDisable: '#E5E5E5' 25 | }; 26 | 27 | const FontColors = { 28 | //字体颜色 29 | fontWhite: '#FFFFFF', 30 | fontBlue: BackgroundColors.blue, //价格,文字链接 31 | fontGreen: '#6CDB03', //提示信息 32 | fontOrange: BackgroundColors.orange, //强提示,标签内容 33 | fontRed: BackgroundColors.red, //警示信息 34 | fontGraylevel1: '#CCCCCC', //内容不可用,文本框内引导文字 35 | fontGraylevel2: '#999999', //次要辅助信息 36 | fontGraylevel3: '#666666', //次要信息 37 | fontGraylevel4: '#333333' //列表,正文标题 38 | }; 39 | 40 | //react中的单位是pt pt=px*(3/4) 四舍五入 41 | const FontSize = { 42 | fontlevel1: 13, 43 | fontlevel2: 17 44 | }; 45 | 46 | export { 47 | BackgroundColors as BackgroundColors, 48 | FontColors as FontColors, 49 | FontSize as FontSize, 50 | ActiveColor as ActiveColor, 51 | DisableColor as DisableColor 52 | }; 53 | -------------------------------------------------------------------------------- /components/Button/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 鲜果FE 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, 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, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /components/Button/README.md: -------------------------------------------------------------------------------- 1 | ###The React-Native-Buttons 2 | 3 | react native button based on pure JavaScript with good expansibility. 4 | 5 | ### Main 6 | 7 | * This component provide 5 theme color for user to chose. 8 | * This component provide 2 type of button for user to chose. 9 | * This component provide the function that user can define their own theme color, we can help them to calculate the disabled color, active color and so on. Also they can define the disabled color and active color by themselves if they like. 10 | * This component provide the ripple effect of the button. And due to lower Android API which do not have this effect, we use highlight as alternative in the consideration of performance. 11 | * This component provide you add as more other components as you can into the button(eg: icon). 12 | 13 | ### Example 14 | * API >= 21 15 | 16 | ![image](https://raw.githubusercontent.com/lulutia/images/master/react-native-button/APIhigh.gif) 17 | 18 | * API < 21 19 | 20 | ![image](https://raw.githubusercontent.com/lulutia/images/master/react-native-button/APIlow.gif) 21 | 22 | ### How to install 23 | 24 | ``` 25 | npm install react-native-buttons --save 26 | ``` 27 | 28 | ### Properties 29 | 30 | | Prop | Default | Type | Description | 31 | | :------------ |:---------------:| :---------------:| :-----| 32 | | type | 'surface' | `string` | Specify the type of the button, you can chose form 'surface' and 'ghost' | 33 | | size | 'default' | `string` | Specify the size of the button, you can chose from 'small', 'default', 'large' | 34 | | theme | 'default' | `string | color type` | Specify the theme color, you can chose from 'orange', 'blue', 'red', 'gray', 'default'. Or you can define your own color by use the colort type(eg: 'gba(221,106,167,0.8)', '#BA55D3' and so on) | 35 | | isLoading | false | `bool` | Specify the button is on loading status. In this status, the button is disabled | 36 | | loadingTitle | 'Loading' | `string` | Specify the text of loading status. | 37 | | loadingColor| - | `color type` | Specify the loading color, if you do not specify this color, we can calculate it for you based on the theme color | 38 | | selfStyle | - | `style type` | Specify button's style by yourself | 39 | | disableColor | - | `color type` | Specify the disabled color, if you do not specify this color, we can calculate it for you based on the theme color | 40 | | active | false | `bool` | Specify the active status of the button | 41 | | disabled | false | `bool` | Specify the disable status of the button| 42 | | activeColor | - | `color type` | Specify the active color, if you do not specify this color, we can calculate it for you based on the theme color| 43 | 44 | ### Method 45 | 46 | see the react native document of TouchableWithoutFeedback. All methods supported by TouchableWithoutFeedback can be used here. 47 | 48 | ### Usage 49 | 50 | * you can see and run the example in the app/index.js. 51 | 52 | ```js 53 | import React, { Component } from 'react'; 54 | import { 55 | AppRegistry, 56 | StyleSheet, 57 | Text, 58 | View 59 | } from 'react-native'; 60 | import {Button} from 'react-native-buttons'; 61 | 62 | class button extends Component { 63 | _onPressButton () { 64 | console.log('onpress'); 65 | } 66 | render() { 67 | return ( 68 | 69 | 76 | 83 | 84 | ); 85 | } 86 | } 87 | 88 | export default button; 89 | 90 | ``` 91 | -------------------------------------------------------------------------------- /components/Button/__tests__/Button.test.js: -------------------------------------------------------------------------------- 1 | import {jsdom} from 'jsdom'; 2 | global.document = jsdom(''); 3 | global.window = document.defaultView; 4 | import React, {Component, propTypes} from 'react'; 5 | import { 6 | Platform, 7 | View, 8 | Text, 9 | ActivityIndicator, 10 | TouchableHighlight, 11 | TouchableNativeFeedback 12 | } from 'react-native'; 13 | import {shallow, mount} from 'enzyme'; 14 | import Button from '../Button'; 15 | 16 | describe('TEST PROPS', () => { 17 | it('check the props', () => { 18 | const wrapper = shallow(); 19 | expect(wrapper.props().type).toEqual('surface'); 20 | expect(wrapper.props().size).toEqual('small'); 21 | expect(wrapper.props().theme).toEqual('orange'); 22 | }); 23 | 24 | it('check loading', () => { 25 | const wrapper1 = shallow( 26 | 35 | ); 36 | expect(wrapper1.props().loadingTitle).toEqual('正在加载'); 37 | expect(wrapper1.props().isLoading).toEqual(true); 38 | expect(wrapper1.find(ActivityIndicator).props().size).toEqual('small'); 39 | }); 40 | 41 | it('check active', () => { 42 | Platform.Version = 20; 43 | const wrapper2 = shallow( 44 | 50 | ); 51 | expect(wrapper2.find(TouchableHighlight).props().disabled).toEqual(false); 52 | expect(wrapper2.find(TouchableNativeFeedback).length).toEqual(0); 53 | }); 54 | 55 | it('check platform', () => { 56 | Platform.Version = 23; 57 | TouchableNativeFeedback.Ripple = function(){}; 58 | const wrapper3 = shallow( 59 | 66 | ); 67 | 68 | // TODO 69 | // expect(wrapper3.find(TouchableHighlight).length).toEqual(0); 70 | // expect(wrapper3.find(TouchableNativeFeedback).length).toEqual(1); 71 | }); 72 | }); 73 | -------------------------------------------------------------------------------- /components/Button/judge.js: -------------------------------------------------------------------------------- 1 | import {Platform} from 'react-native'; 2 | 3 | export function judgePlatformLevel(module) { 4 | const level = Platform.Version; 5 | if (module === 'TouchableNativeFeedback') { 6 | return level >= 21; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /components/Button/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-buttons", 3 | "version": "0.0.4", 4 | "description": "react native button for android.", 5 | "main": "Button.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/xgfe/react-native-ui-xg.git" 9 | }, 10 | "keywords": [ 11 | "react-native", 12 | "Button" 13 | ], 14 | "author": "xgfe", 15 | "license": "MIT", 16 | "bugs": { 17 | "url": "https://github.com/xgfe/react-native-ui-xg/issues" 18 | }, 19 | "homepage": "https://github.com/xgfe/react-native-datepicker/components/Button#readme", 20 | "dependencies": { 21 | "react-native-stylesheet-xg": "^1.0.3", 22 | "react-native-colortool": "^0.0.1" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /components/CalendarSelect/.npmignore: -------------------------------------------------------------------------------- 1 | example 2 | __tests__ 3 | .* 4 | -------------------------------------------------------------------------------- /components/CalendarSelect/CalendarStyle.js: -------------------------------------------------------------------------------- 1 | import { 2 | StyleSheet, 3 | Dimensions 4 | } from 'react-native'; 5 | const {scale, width} = Dimensions.get('window'); 6 | let iconSize = 22; 7 | let resultFontSize = 24; 8 | let weekTextFontSize = 16; 9 | let slashLength = 80; 10 | if (width < 350) { 11 | resultFontSize = 20; 12 | weekTextFontSize = 14; 13 | iconSize = 20; 14 | slashLength = 70; 15 | } 16 | 17 | export default StyleSheet.create({ 18 | container: { 19 | flex: 1 20 | }, 21 | ctrl: { 22 | flex: 1.5, 23 | justifyContent: 'space-between', 24 | flexDirection: 'row', 25 | alignItems: 'flex-end', 26 | paddingHorizontal: 15 27 | }, 28 | result: { 29 | flex: 2.5, 30 | paddingHorizontal: 15, 31 | flexDirection: 'row', 32 | alignItems: 'center', 33 | justifyContent: 'space-between' 34 | }, 35 | resultSlash: { 36 | width: slashLength, 37 | height: 1 / scale, 38 | transform: [ 39 | { 40 | rotateZ: '-45deg' 41 | } 42 | ] 43 | }, 44 | resultPart: { 45 | flex: 1 46 | }, 47 | resultText: { 48 | fontSize: resultFontSize, 49 | marginVertical: 4, 50 | fontWeight: '200' 51 | }, 52 | clearText: { 53 | fontSize: 18, 54 | fontWeight: '400' 55 | }, 56 | startText: { 57 | textAlign: 'left' 58 | }, 59 | endText: { 60 | textAlign: 'right' 61 | }, 62 | week: { 63 | flex: 1, 64 | flexDirection: 'row', 65 | justifyContent: 'space-between', 66 | alignItems: 'center' 67 | }, 68 | weekText: { 69 | flex: 1, 70 | fontSize: weekTextFontSize, 71 | textAlign: 'center' 72 | }, 73 | scroll: { 74 | flex: 9, 75 | borderTopWidth: 1, 76 | borderBottomWidth: 1 77 | }, 78 | scrollArea: { 79 | flex: 1 80 | }, 81 | btn: { 82 | flex: 1.5, 83 | justifyContent: 'center', 84 | alignItems: 'center' 85 | }, 86 | confirmContainer: { 87 | overflow: 'hidden', 88 | backgroundColor: 'rgba(255, 255, 255, 0.40)', 89 | borderRadius: 4, 90 | margin: 14, 91 | flex: 1, 92 | alignSelf: 'stretch', 93 | justifyContent: 'center' 94 | }, 95 | confirmContainerDisabled: { 96 | backgroundColor: 'rgba(255, 255, 255, 0.20)' 97 | }, 98 | confirmText: { 99 | fontSize: 16, 100 | fontWeight: 'bold', 101 | textAlign: 'center' 102 | }, 103 | confirmTextDisabled: { 104 | color: 'rgba(255, 255, 255, 0.40)' 105 | }, 106 | closeIcon: { 107 | width: iconSize, 108 | height: iconSize 109 | } 110 | }); 111 | -------------------------------------------------------------------------------- /components/CalendarSelect/Day/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by TinySymphony on 2017-05-11. 3 | */ 4 | 5 | import React, {PropTypes, Component} from 'react'; 6 | import { 7 | View, 8 | Text, 9 | StyleSheet, 10 | TouchableHighlight 11 | } from 'react-native'; 12 | import Moment from 'moment'; 13 | import styles from './style'; 14 | 15 | export default class Day extends Component { 16 | static propTypes = { 17 | onChoose: PropTypes.func 18 | } 19 | constructor (props) { 20 | super(props); 21 | this._chooseDay = this._chooseDay.bind(this); 22 | this._statusCheck = this._statusCheck.bind(this); 23 | this._statusCheck(); 24 | } 25 | _chooseDay () { 26 | this.props.onChoose && this.props.onChoose(this.props.date); 27 | } 28 | _statusCheck (props) { 29 | const { 30 | startDate, 31 | endDate, 32 | today, 33 | date = null, 34 | minDate, 35 | maxDate, 36 | empty 37 | } = props || this.props; 38 | this.isToday = today.isSame(date, 'd'); 39 | this.isValid = date && 40 | (date >= minDate || date.isSame(minDate, 'd')) && 41 | (date <= maxDate || date.isSame(maxDate, 'd')); 42 | this.isMid = date > startDate && date < endDate || 43 | (!date && empty >= startDate && empty <= endDate); 44 | this.isStart = date && date.isSame(startDate, 'd'); 45 | this.isStartPart = this.isStart && endDate; 46 | this.isEnd = date && date.isSame(endDate, 'd'); 47 | this.isFocus = this.isMid || this.isStart || this.isEnd; 48 | return this.isFocus; 49 | } 50 | shouldComponentUpdate (nextProps) { 51 | let prevStatus = this.isFocus; 52 | let nextStatus = this._statusCheck(nextProps); 53 | if (prevStatus || nextStatus) return true; 54 | return false; 55 | } 56 | render () { 57 | const { 58 | date, 59 | color 60 | } = this.props; 61 | let text = date ? date.date() : ''; 62 | let mainColor = {color: color.mainColor}; 63 | let subColor = {color: color.subColor}; 64 | let mainBack = {backgroundColor: color.mainColor}; 65 | let subBack = {backgroundColor: color.subColor}; 66 | return ( 67 | 75 | {this.isValid ? 76 | 80 | {text} 81 | : 82 | 83 | {text} 84 | 85 | } 86 | 87 | ); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /components/CalendarSelect/Day/style.js: -------------------------------------------------------------------------------- 1 | import { 2 | StyleSheet, 3 | Dimensions 4 | } from 'react-native'; 5 | const {scale, width} = Dimensions.get('window'); 6 | let dayWidth = width / 7; 7 | let mod = scale * width % 7; 8 | if (mod) { 9 | dayWidth = ((7 - mod) / scale + width) / 7; 10 | } 11 | export default StyleSheet.create({ 12 | dayContainer: { 13 | width: dayWidth, 14 | justifyContent: 'center', 15 | alignItems: 'center' 16 | }, 17 | startContainer: { 18 | borderTopLeftRadius: 100, 19 | borderBottomLeftRadius: 100 20 | }, 21 | endContainer: { 22 | borderTopRightRadius: 100, 23 | borderBottomRightRadius: 100 24 | }, 25 | today: { 26 | borderWidth: 1, 27 | borderColor: 'rgba(255, 255, 255, 0.40)' 28 | }, 29 | day: { 30 | width: dayWidth, 31 | height: dayWidth, 32 | borderRadius: dayWidth / 2, 33 | overflow: 'hidden', 34 | justifyContent: 'center', 35 | alignItems: 'center' 36 | }, 37 | dayText: { 38 | fontSize: 16, 39 | fontWeight: '400', 40 | textAlign: 'center' 41 | }, 42 | dayTextDisabled: { 43 | fontSize: 16, 44 | color: 'rgba(255, 255, 255, 0.54)', 45 | textAlign: 'center' 46 | } 47 | }); 48 | -------------------------------------------------------------------------------- /components/CalendarSelect/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 鲜果FE 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, 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, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /components/CalendarSelect/Month/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by TinySymphony on 2017-05-11. 3 | */ 4 | 5 | import React, {PropTypes, Component} from 'react'; 6 | import { 7 | View, 8 | Text, 9 | StyleSheet, 10 | TouchableHighlight 11 | } from 'react-native'; 12 | import Moment from 'moment'; 13 | import styles from './style'; 14 | import Day from '../Day'; 15 | 16 | export default class Month extends Component { 17 | constructor (props) { 18 | super(props); 19 | this._getDayList = this._getDayList.bind(this); 20 | this._renderDayRow = this._renderDayRow.bind(this); 21 | this._getMonthText = this._getMonthText.bind(this); 22 | } 23 | static I18N_MAP = { 24 | 'zh': [ 25 | '一月', '二月', '三月', '四月', '五月', '六月', 26 | '七月', '八月', '九月', '十月', '十一月', '十二月' 27 | ], 28 | 'jp': [ 29 | '一月', '二月', '三月', '四月', '五月', '六月', 30 | '七月', '八月', '九月', '十月', '十一月', '十二月' 31 | ], 32 | 'en': [ 33 | 'January', 'February', 'March', 'April', 'May', 'June', 34 | 'July', 'August', 'September', 'October', 'November', 'December' 35 | ] 36 | } 37 | _getMonthText () { 38 | const { 39 | month, 40 | today, 41 | i18n 42 | } = this.props; 43 | let y = month.year(); 44 | let m = month.month(); 45 | let year = today.year(); 46 | if (year === y) { 47 | return Month.I18N_MAP[i18n][m]; 48 | } else { 49 | if (i18n === 'en') { 50 | return `${Month.I18N_MAP[i18n][m]}, ${y}`; 51 | } 52 | return month.format('YYYY年M月'); 53 | } 54 | } 55 | _getDayList (date) { 56 | let dayList; 57 | let month = date.month(); 58 | let weekday = date.isoWeekday(); 59 | if (weekday === 7) { 60 | dayList = []; 61 | } else { 62 | dayList = new Array(weekday).fill({ 63 | empty: date.clone().subtract(1, 'h') 64 | }); 65 | } 66 | while (date.month() === month) { 67 | dayList.push({ 68 | date: date.clone() 69 | }); 70 | date.add(1, 'days'); 71 | } 72 | date.subtract(1, 'days'); 73 | weekday = date.isoWeekday(); 74 | if (weekday === 7) { 75 | return dayList.concat(new Array(6).fill({ 76 | empty: date.clone().hour(1) 77 | })); 78 | } 79 | return dayList.concat(new Array(Math.abs(weekday - 6)).fill({ 80 | empty: date.clone().hour(1) 81 | })); 82 | } 83 | _renderDayRow (dayList, index) { 84 | const { 85 | startDate, 86 | endDate, 87 | today 88 | } = this.props; 89 | return ( 90 | 91 | {dayList.map((item, i) => 92 | 97 | )} 98 | 99 | ); 100 | } 101 | render () { 102 | const { 103 | month, 104 | today, 105 | color 106 | } = this.props; 107 | let subColor = {color: color.subColor}; 108 | let titleText = this._getMonthText(); 109 | let dayList = this._getDayList(month.clone()); 110 | let rowArray = new Array(dayList.length / 7).fill(''); 111 | return ( 112 | 113 | 114 | {titleText} 115 | 116 | 117 | {rowArray.map((item, i) => 118 | this._renderDayRow(dayList.slice(i * 7, i * 7 + 7), i) 119 | )} 120 | 121 | 122 | ); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /components/CalendarSelect/Month/style.js: -------------------------------------------------------------------------------- 1 | import { 2 | StyleSheet, 3 | Dimensions 4 | } from 'react-native'; 5 | const {scale, width} = Dimensions.get('window'); 6 | 7 | export default StyleSheet.create({ 8 | month: { 9 | paddingTop: 15, 10 | paddingBottom: 10 11 | }, 12 | monthTitle: { 13 | paddingHorizontal: 20 14 | }, 15 | monthTitleText: { 16 | fontSize: 24, 17 | lineHeight: 24, 18 | fontWeight: '300' 19 | }, 20 | dayRow: { 21 | flex: 1, 22 | flexDirection: 'row', 23 | alignSelf: 'stretch', 24 | alignItems: 'center', 25 | paddingVertical: 5 26 | } 27 | }); 28 | -------------------------------------------------------------------------------- /components/CalendarSelect/example/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by TinySymphony on 2017-05-17. 3 | */ 4 | 5 | import React, {Component} from 'react'; 6 | import { 7 | StyleSheet, 8 | View, 9 | Text, 10 | TouchableHighlight 11 | } from 'react-native'; 12 | 13 | import CalendarSelect from '../index'; 14 | 15 | export default class CalendarSelectExample extends Component { 16 | constructor(props) { 17 | super(props); 18 | this.calendar = null; 19 | this.state = { 20 | startDate: new Date(2017, 7, 12), 21 | endDate: new Date(2017, 8, 23) 22 | }; 23 | this.openCalendar = this.openCalendar.bind(this); 24 | this.confirmDate = this.confirmDate.bind(this); 25 | } 26 | confirmDate ({startDate, endDate, startMoment, endMoment}) { 27 | this.setState({ 28 | startDate, 29 | endDate 30 | }); 31 | } 32 | openCalendar() { 33 | this.refs.cal && this.refs.cal.open(); 34 | } 35 | render() { 36 | let color = { 37 | mainColor: '#138691' 38 | }; 39 | const { 40 | startDate, 41 | endDate 42 | } = this.state; 43 | let text = startDate && endDate ? startDate.toLocaleDateString() + ' --- ' + endDate.toLocaleDateString() : 44 | 'Please select a period'; 45 | return ( 46 | 47 | 52 | Choose start & end Time 53 | 54 | 55 | {text} 56 | 57 | 68 | 69 | ); 70 | } 71 | } 72 | 73 | const styles = StyleSheet.create({ 74 | example: { 75 | flex: 1, 76 | justifyContent: 'center', 77 | alignItems: 'center' 78 | }, 79 | btn: { 80 | paddingHorizontal: 20, 81 | paddingVertical: 10, 82 | overflow: 'hidden', 83 | borderRadius: 6, 84 | marginBottom: 30, 85 | backgroundColor: '#db9c0e' 86 | }, 87 | btnFont: { 88 | color: '#fff', 89 | fontSize: 20 90 | }, 91 | font: { 92 | fontSize: 24, 93 | fontWeight: '500', 94 | color: '#4c575c' 95 | } 96 | }); 97 | -------------------------------------------------------------------------------- /components/CalendarSelect/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-calendar-select", 3 | "version": "0.1.0", 4 | "description": "Calendar component for react-native, helps users select a date period, like Airbnb.", 5 | "main": "./index.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/xgfe/react-native-ui-xg.git" 9 | }, 10 | "keywords": [ 11 | "react-native", 12 | "react-native-calendar-xg", 13 | "calendar", 14 | "xgfe" 15 | ], 16 | "author": "xgfe", 17 | "license": "MIT", 18 | "bugs": { 19 | "url": "https://github.com/xgfe/react-native-ui-xg/issues" 20 | }, 21 | "homepage": "https://github.com/xgfe/react-native-ui-xg#readme", 22 | "dependencies": { 23 | "moment": "^2.18.1" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /components/Confirm/.npmignore: -------------------------------------------------------------------------------- 1 | example/ 2 | __tests__/ 3 | .* 4 | components/ 5 | coverage/ 6 | index.android.js 7 | index.ios.js 8 | android/ 9 | ios/ 10 | -------------------------------------------------------------------------------- /components/Confirm/Confirm.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import { 3 | Text, 4 | View, 5 | Modal 6 | } from 'react-native'; 7 | import Style from './ConfirmStyle'; 8 | import Button from 'react-native-buttons'; 9 | import Input from 'react-native-input-xg'; 10 | 11 | class Confirm extends Component { 12 | 13 | // 构造 14 | constructor(props) { 15 | super(props); 16 | // 初始状态 17 | this.state = { 18 | modalVisible: false, 19 | title: null, 20 | text: null, 21 | content: null, 22 | comment: null, 23 | commentRequired: false, 24 | disableCancel: false, 25 | confirmText: '确定', 26 | cancelText: '取消' 27 | }; 28 | 29 | this.open = this.open.bind(this); 30 | this.onCancel = this.onCancel.bind(this); 31 | this.onConfirm = this.onConfirm.bind(this); 32 | } 33 | 34 | open(options) { 35 | const { 36 | title = null, text = null, content = null, comment = null, 37 | commentRequired = false, disableCancel = false, confirmText = '确定', cancelText = '取消' 38 | } = options; 39 | 40 | this._cacheOptions = options; 41 | 42 | this.setState({ 43 | title, 44 | text, 45 | content, 46 | comment: undefined, 47 | commentPlaceholder: comment, 48 | commentRequired, 49 | modalVisible: true, 50 | disableCancel, 51 | confirmText, 52 | cancelText 53 | }); 54 | } 55 | 56 | onCancel() { 57 | const {cancel} = this._cacheOptions; 58 | 59 | if (typeof cancel === 'function') { 60 | cancel(); 61 | } 62 | 63 | this._cacheOptions = null; 64 | this.setState({ 65 | modalVisible: false 66 | }); 67 | } 68 | 69 | onConfirm() { 70 | const {comment = null, confirm} = this._cacheOptions; 71 | let confirmResult = false; 72 | 73 | if (typeof confirm === 'function') { 74 | confirmResult = confirm(comment ? { 75 | comment: this.state.comment 76 | } : undefined); 77 | } 78 | 79 | // 返回值false时关闭弹窗, 返回true不做处理 80 | if (!confirmResult) { 81 | this.setState({ 82 | modalVisible: false 83 | }); 84 | } else if (confirmResult instanceof Promise) { 85 | // 返回Promise时, promise成功后关闭 86 | confirmResult.then(() => { 87 | this.setState({ 88 | modalVisible: false 89 | }); 90 | }); 91 | } else { 92 | return undefined; 93 | } 94 | } 95 | 96 | render() { 97 | const { 98 | title, text, content, confirmText, cancelText, comment, commentPlaceholder, modalVisible, commentRequired, disableCancel 99 | } = this.state; 100 | 101 | return ( 102 | { 107 | console.debug('close'); 108 | }} 109 | > 110 | 111 | 112 | {title && 113 | {title} 114 | } 115 | 116 | {text && {text}} 117 | {content} 118 | {commentPlaceholder && 119 | this.setState({ 121 | comment: inputText 122 | })} 123 | placeholder={commentPlaceholder} 124 | />} 125 | 126 | 127 | 128 | {!disableCancel && 129 | } 134 | 140 | 141 | 142 | 143 | 144 | ); 145 | } 146 | } 147 | 148 | export default Confirm; 149 | -------------------------------------------------------------------------------- /components/Confirm/ConfirmStyle.js: -------------------------------------------------------------------------------- 1 | import StyleSheet from 'react-native-stylesheet-xg'; 2 | 3 | const Style = StyleSheet.create({ 4 | wrapper: { 5 | flex: 1, 6 | justifyContent: 'center', 7 | alignItems: 'center', 8 | backgroundColor: '#00000099' 9 | }, 10 | body: { 11 | width: 300, 12 | backgroundColor: '#ffffff' 13 | }, 14 | title: { 15 | height: 40, 16 | justifyContent: 'center', 17 | alignItems: 'center', 18 | borderBottomWidth: 1, 19 | borderBottomColor: '#e5e5e5' 20 | }, 21 | content: { 22 | padding: 25, 23 | paddingLeft: 10, 24 | paddingRight: 10 25 | }, 26 | footerBtn: { 27 | flex: 1, 28 | height: 40, 29 | borderRadius: 0, 30 | alignSelf: 'stretch' 31 | }, 32 | outerView: { 33 | color: '#06c1ae', 34 | fontSize: 15 35 | }, 36 | subText: { 37 | fontSize: 14, 38 | fontFamily: 'Arial', 39 | color: '#666' 40 | }, 41 | innerView: { 42 | height: 40, 43 | flexDirection: 'row', 44 | alignItems: 'center', 45 | backgroundColor: 'red' 46 | } 47 | }); 48 | 49 | export default Style; 50 | -------------------------------------------------------------------------------- /components/Confirm/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 鲜果FE 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, 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, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /components/Confirm/README.md: -------------------------------------------------------------------------------- 1 | ### The react-native-confirm 2 | * react native confirm component for both Android and iOS based on pure JavaScript 3 | 4 | ### Main 5 | * This component provide some more functions besides the basic Modal RN provided 6 | 7 | ### Properties 8 | * Besides the basic properties RN provided, we also provide belows: 9 | 10 | ![image](https://raw.githubusercontent.com/lulutia/images/master/react-native-components/Screen-Capture-40.gif) 11 | 12 | ### Properties 13 | 14 | | Prop | Default | Type | Description | 15 | | :------------ |:---------------:| :---------------:| :-----| 16 | | title | - | `string` | Specify the title of the confirm | 17 | | text | - | `string` | Specify the text you want to show in the content | 18 | | content | - | `node` | Support you custome your own content| 19 | | comment | - | `string` | Specify the comment in the input| 20 | | commentRequired | false | `bool` | If you must type sth in the input | 21 | | disableCancel| false | `bool` | Do not show the cancel button | 22 | | confirmText | '确定' | `string` | Specify the text of the confirm button | 23 | | cancelText | '取消' | `string` | Specify the text of the cancel button | 24 | |cancel | - | 'func' | callback when you cancel| 25 | |confirm | - | 'func' | callback when you confirm| 26 | 27 | -------------------------------------------------------------------------------- /components/Confirm/__tests__/Confirm.test.js: -------------------------------------------------------------------------------- 1 | import {jsdom} from 'jsdom'; 2 | global.document = jsdom(''); 3 | global.window = document.defaultView; 4 | import React from 'react'; 5 | import { 6 | Text, 7 | Modal 8 | } from 'react-native'; 9 | import renderer from 'react-test-renderer'; 10 | import {shallow, mount} from 'enzyme'; 11 | import Confirm from '../Confirm'; 12 | import Button from 'react-native-buttons'; 13 | import Input from 'react-native-input-xg'; 14 | 15 | console.error = function () {}; 16 | 17 | describe('test node', () => { 18 | it('check node number', () => { 19 | const wrapper = mount(); 20 | expect(wrapper.find(Modal).length).toEqual(1); 21 | expect(wrapper.find(Input).length).toEqual(0); 22 | expect(wrapper.find(Button).length).toEqual(2); 23 | }); 24 | }); 25 | 26 | describe('test props', () => { 27 | 28 | it('check props', () => { 29 | const wrapper1 = mount( 30 | ); 35 | expect(wrapper1.prop('title')).toEqual('age'); 36 | expect(wrapper1.prop('confirmText')).toEqual("can't fix"); 37 | expect(wrapper1.prop('cancelText')).toEqual('cancel'); 38 | }); 39 | }); 40 | 41 | describe('test fun', () => { 42 | 43 | it('check open', () => { 44 | const wrapper1 = shallow( 45 | ); 50 | let instance = wrapper1.instance(); 51 | instance.open({title: 'age'}); 52 | expect(wrapper1.state('title')).toEqual('age'); 53 | }); 54 | 55 | it('check onCancel', () => { 56 | let temp = false; 57 | const wrapper2 = shallow( 58 | ); 63 | let instance = wrapper2.instance(); 64 | instance._cacheOptions = {cancel: function(){temp = true;}}; 65 | instance.onCancel(); 66 | expect(temp).toEqual(true); 67 | expect(wrapper2.state('modalVisible')).toEqual(false); 68 | }); 69 | 70 | it('checkout confirm', () => { 71 | let temp = false; 72 | const wrapper3 = shallow( 73 | ); 77 | let instance = wrapper3.instance(); 78 | instance._cacheOptions = {comment: 'good', confirm: function(){temp = true;}}; 79 | instance.onConfirm(); 80 | expect(temp).toEqual(true); 81 | 82 | let instance1 = wrapper3.instance(); 83 | instance1._cacheOptions = {confirm: 't'}; 84 | instance1.onConfirm(); 85 | expect(wrapper3.state('modalVisible')).toEqual(false); 86 | }); 87 | }); 88 | 89 | describe('check branch', () => { 90 | it('check text and input', () => { 91 | const wrapper = shallow( 92 | ); 93 | let instance = wrapper.instance(); 94 | instance.open({comment: 'test', text: 'tt'}); 95 | expect(wrapper.find(Input).length).toEqual(1); 96 | expect(wrapper.find(Text).length).toEqual(1); 97 | let instance1 = wrapper.instance(); 98 | instance1.open({confirm: () => {return true;}}); 99 | instance1.onConfirm(); 100 | expect(wrapper.state('modalVisible')).toEqual(true); 101 | 102 | let instance2 = wrapper.instance(); 103 | instance2.open({confirm: () => {return Promise.resolve('a success');}}); 104 | expect(wrapper.state('modalVisible')).toEqual(true); 105 | instance2.onConfirm(); 106 | }); 107 | }); 108 | 109 | 110 | -------------------------------------------------------------------------------- /components/Confirm/example/index.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import { 3 | StyleSheet, 4 | Text, 5 | View 6 | } from 'react-native'; 7 | import Confirm from '../Confirm'; 8 | import Button from 'react-native-buttons'; 9 | 10 | export default class confirm extends Component { 11 | 12 | constructor(props) { 13 | super(props); 14 | this.state = { 15 | test1: '', 16 | test2: '12', 17 | test3: '', 18 | test4: '', 19 | test5: '', 20 | test6: '', 21 | test7: '' 22 | }; 23 | } 24 | _onPressButton(number) { 25 | switch (number) { 26 | case 1: 27 | this.refs.confirm.open({ 28 | content: 29 | ( 30 | 地址将修改为:测试地址 31 | 该地址会影响之后的操作,请谨慎修改 32 | ), 33 | confirm: () => { 34 | return; 35 | } 36 | }); 37 | break; 38 | case 2: 39 | this.refs.confirm1.open({ 40 | title: 'user-defined', 41 | comment: 'just a test', 42 | confirmText: 'Confirm', 43 | cancelText: 'Cancel', 44 | confirm: () => { 45 | return; 46 | } 47 | }); 48 | break; 49 | case 3: 50 | this.refs.confirm2.open({ 51 | title: 'cancel disable', 52 | comment: 'just a test', 53 | commentRequired: true, 54 | disableCancel: true, 55 | cancelText: 'Cancel', 56 | confirm: () => { 57 | return; 58 | } 59 | }); 60 | break; 61 | default: return; 62 | } 63 | } 64 | render() { 65 | return ( 66 | 67 | 71 | 76 | 81 | 82 | 83 | 84 | 85 | ); 86 | } 87 | } 88 | 89 | const styles = StyleSheet.create({ 90 | container: { 91 | flex: 1, 92 | justifyContent: 'center', 93 | alignItems: 'center' 94 | }, 95 | footerBtn: { 96 | height: 40, 97 | borderRadius: 0, 98 | alignSelf: 'stretch' 99 | }, 100 | welcome: { 101 | fontSize: 20, 102 | textAlign: 'center', 103 | margin: 10 104 | }, 105 | instructions: { 106 | textAlign: 'center', 107 | color: '#333333', 108 | marginBottom: 5 109 | } 110 | }); 111 | -------------------------------------------------------------------------------- /components/Confirm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-confirm", 3 | "version": "0.0.1", 4 | "description": "react native confirm component for both Android and IOS, useing pure JavaScript", 5 | "main": "Confirm.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/xgfe/react-native-ui-xg.git" 9 | }, 10 | "keywords": [ 11 | "react-native", 12 | "confirm", 13 | "react-native-confirm" 14 | ], 15 | "author": "xgfe", 16 | "license": "MIT", 17 | "bugs": { 18 | "url": "https://github.com/xgfe/react-native-ui-xg/issues" 19 | }, 20 | "homepage": "https://github.com/xgfe/react-native-ui-xg/components/Confirm#readme", 21 | "dependencies": { 22 | "react-native-stylesheet-xg": "^1.1.0", 23 | "react-native-buttons": "^0.0.3", 24 | "react-native-input-xg": "^0.0.2" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /components/DatePicker/.npmignore: -------------------------------------------------------------------------------- 1 | example 2 | __tests__ 3 | .* 4 | -------------------------------------------------------------------------------- /components/DatePicker/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 鲜果FE 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, 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, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /components/DatePicker/date_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xgfe/react-native-ui-xg/59f111fdb0fcb416948212f941d2fc2f486d4adb/components/DatePicker/date_icon.png -------------------------------------------------------------------------------- /components/DatePicker/example/google_calendar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xgfe/react-native-ui-xg/59f111fdb0fcb416948212f941d2fc2f486d4adb/components/DatePicker/example/google_calendar.png -------------------------------------------------------------------------------- /components/DatePicker/example/index.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import { 3 | StyleSheet, 4 | Text, 5 | View, 6 | PanResponder 7 | } from 'react-native'; 8 | import DatePicker from '../Datepicker.js'; 9 | 10 | class datepicker extends Component { 11 | 12 | constructor(props) { 13 | super(props); 14 | 15 | this.state = { 16 | date: '', 17 | time: '20:00', 18 | datetime: '2016-05-05 20:00', 19 | datetime1: '2016-05-05 20:00' 20 | }; 21 | } 22 | 23 | componentWillMount() { 24 | this._panResponder = PanResponder.create({ 25 | onStartShouldSetPanResponder: (e) => {console.log('onStartShouldSetPanResponder'); return true;}, 26 | onMoveShouldSetPanResponder: (e) => {console.log('onMoveShouldSetPanResponder'); return true;}, 27 | onPanResponderGrant: (e) => console.log('onPanResponderGrant'), 28 | onPanResponderMove: (e) => console.log('onPanResponderMove'), 29 | onPanResponderRelease: (e) => console.log('onPanResponderRelease'), 30 | onPanResponderTerminate: (e) => console.log('onPanResponderTerminate') 31 | }); 32 | } 33 | 34 | render() { 35 | return ( 36 | 37 | 38 | Welcome to react-native-datepicker example! 39 | 40 | {this.setState({date: date});}} 52 | /> 53 | date: {this.state.date} 54 | {this.setState({time: time});}} 63 | /> 64 | time: {this.state.time} 65 | {this.setState({datetime: datetime});}} 74 | /> 75 | datetime: {this.state.datetime} 76 | {this.setState({datetime1: datetime});}} 96 | /> 97 | datetime: {this.state.datetime1} 98 | 99 | ); 100 | } 101 | } 102 | 103 | const styles = StyleSheet.create({ 104 | container: { 105 | flex: 1, 106 | justifyContent: 'center', 107 | alignItems: 'center' 108 | }, 109 | welcome: { 110 | fontSize: 20, 111 | textAlign: 'center', 112 | margin: 10 113 | }, 114 | instructions: { 115 | textAlign: 'center', 116 | color: '#333333', 117 | marginBottom: 5 118 | } 119 | }); 120 | 121 | export default datepicker; 122 | -------------------------------------------------------------------------------- /components/DatePicker/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-datepicker", 3 | "version": "1.5.0", 4 | "description": "react native datePicker component for both Android and IOS, useing DatePikcerAndroid, TimePickerAndroid and DatePickerIOS", 5 | "main": "Datepicker.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/xgfe/react-native-ui-xg.git" 9 | }, 10 | "keywords": [ 11 | "react-native", 12 | "DatePicker" 13 | ], 14 | "author": "xgfe", 15 | "license": "MIT", 16 | "bugs": { 17 | "url": "https://github.com/xgfe/react-native-ui-xg/issues" 18 | }, 19 | "homepage": "https://github.com/xgfe/react-native-datepicker/components/Datepicker#readme", 20 | "dependencies": { 21 | "moment": "2.x.x" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /components/DatePicker/style.js: -------------------------------------------------------------------------------- 1 | import {StyleSheet} from 'react-native'; 2 | 3 | let style = StyleSheet.create({ 4 | dateTouch: { 5 | width: 142 6 | }, 7 | dateTouchBody: { 8 | flexDirection: 'row', 9 | height: 40, 10 | alignItems: 'center', 11 | justifyContent: 'center' 12 | }, 13 | dateIcon: { 14 | width: 32, 15 | height: 32, 16 | marginLeft: 5, 17 | marginRight: 5 18 | }, 19 | dateInput: { 20 | flex: 1, 21 | height: 40, 22 | borderWidth: 1, 23 | borderColor: '#aaa', 24 | alignItems: 'center', 25 | justifyContent: 'center' 26 | }, 27 | dateText: { 28 | color: '#333' 29 | }, 30 | placeholderText: { 31 | color: '#c9c9c9' 32 | }, 33 | datePickerMask: { 34 | flex: 1, 35 | alignItems: 'flex-end', 36 | flexDirection: 'row', 37 | backgroundColor: '#00000077' 38 | }, 39 | datePickerCon: { 40 | backgroundColor: '#fff', 41 | height: 0, 42 | overflow: 'hidden' 43 | }, 44 | btnText: { 45 | position: 'absolute', 46 | top: 0, 47 | height: 42, 48 | padding: 20, 49 | flexDirection: 'row', 50 | alignItems: 'center', 51 | justifyContent: 'center' 52 | }, 53 | btnTextText: { 54 | fontSize: 16, 55 | color: '#46cf98' 56 | }, 57 | btnTextCancel: { 58 | color: '#666' 59 | }, 60 | btnCancel: { 61 | left: 0 62 | }, 63 | btnConfirm: { 64 | right: 0 65 | }, 66 | datePicker: { 67 | marginTop: 42, 68 | borderTopColor: '#ccc', 69 | borderTopWidth: 1 70 | }, 71 | disabled: { 72 | backgroundColor: '#eee' 73 | } 74 | }); 75 | 76 | export default style; 77 | -------------------------------------------------------------------------------- /components/Drawer/.npmignore: -------------------------------------------------------------------------------- 1 | example 2 | __tests__ 3 | .* 4 | -------------------------------------------------------------------------------- /components/Drawer/Animation.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by TinySymphony on 2017-02-14. 3 | */ 4 | 5 | export default function Animation(option) { 6 | this.animate = this.animate.bind(this); 7 | this.start = this.start.bind(this); 8 | this.option = option; 9 | } 10 | 11 | Animation.prototype.animate = function (now) { 12 | const { 13 | start, 14 | end, 15 | duration, 16 | onAnimationFrame, 17 | onAnimationEnd, 18 | easingFunc = this.defaultEasing 19 | } = this.option; 20 | 21 | let currentDuration = now - this.startTime; 22 | if (currentDuration >= duration) { 23 | onAnimationFrame(end); 24 | onAnimationEnd(); 25 | return; 26 | } 27 | let value; 28 | if (start > end) { 29 | value = start - (start - end) * easingFunc(currentDuration / duration); 30 | } else { 31 | value = (end - start) * easingFunc(currentDuration / duration) + start; 32 | } 33 | onAnimationFrame(value); 34 | requestAnimationFrame(this.animate); 35 | }; 36 | 37 | Animation.prototype.start = function (time) { 38 | this.startTime = new Date(); 39 | this.animate(time || this.startTime); 40 | }; 41 | 42 | Animation.prototype.defaultEasing = t => t; 43 | -------------------------------------------------------------------------------- /components/Drawer/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 鲜果FE 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, 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, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /components/Drawer/example/index.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import { 3 | StyleSheet, 4 | Text, 5 | View, 6 | Dimensions, 7 | Easing, 8 | TouchableHighlight 9 | } from 'react-native'; 10 | 11 | import Drawer from '../index'; 12 | 13 | const {width, height} = Dimensions.get('window'); 14 | 15 | export default class DrawerExample extends Component { 16 | render() { 17 | var drawerContent = ( 18 | 19 | 20 | Drag / click the left side to close drawer. 21 | Or click the button bellow. 22 | {this.drawer && this.drawer.closeDrawer();}}> 26 | Close Drawer 27 | 28 | 29 | 30 | ); 31 | return ( 32 | {this.drawer = drawer;}} 34 | style={styles.container} 35 | drawerWidth={width} 36 | drawerContent={drawerContent} 37 | type={Drawer.types.Default} 38 | customStyles={{drawer: styles.drawer}} 39 | drawerPosition={Drawer.positions.Left} 40 | easingFunc={Easing.ease} 41 | > 42 | 43 | React Native Drawer Menu 44 | Drag the right side to open drawer. 45 | Or click the button bellow. 46 | {this.drawer && this.drawer.openDrawer();}}> 50 | Open Drawer 51 | 52 | 53 | 54 | ); 55 | } 56 | } 57 | 58 | const styles = StyleSheet.create({ 59 | returnView: { 60 | flex: 1, 61 | justifyContent: 'center', 62 | alignItems: 'center' 63 | }, 64 | btn: { 65 | marginTop: 10, 66 | padding: 10, 67 | overflow: 'hidden', 68 | borderRadius: 5, 69 | backgroundColor: '#f06355' 70 | }, 71 | closeBtn: { 72 | backgroundColor: '#13c9e9' 73 | }, 74 | btnText: { 75 | fontSize: 14, 76 | color: '#f0f0f0' 77 | }, 78 | name: { 79 | fontSize: 20, 80 | marginBottom: 15 81 | }, 82 | container: { 83 | flex: 1, 84 | justifyContent: 'center', 85 | alignItems: 'center' 86 | }, 87 | main: { 88 | position: 'absolute', 89 | backgroundColor: '#2ba' 90 | }, 91 | content: { 92 | flex: 1, 93 | justifyContent: 'center', 94 | alignItems: 'center', 95 | alignSelf: 'stretch' 96 | }, 97 | drawerContent: { 98 | flex: 1, 99 | justifyContent: 'center', 100 | alignItems: 'center' 101 | }, 102 | leftBottom: { 103 | flex: 2, 104 | justifyContent: 'space-around', 105 | alignItems: 'stretch', 106 | alignSelf: 'stretch', 107 | backgroundColor: '#f0f0f0' 108 | }, 109 | drawer: { 110 | shadowColor: '#000', 111 | shadowOpacity: 0.4, 112 | shadowRadius: 10 113 | } 114 | }); 115 | -------------------------------------------------------------------------------- /components/Drawer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-drawer-menu", 3 | "version": "0.2.3", 4 | "description": "react native drawer component for both Android and IOS", 5 | "keywords": [ 6 | "react-native", 7 | "drawer" 8 | ], 9 | "main": "Drawer/index.js", 10 | "author": "xgfe", 11 | "maintainers": [ 12 | { 13 | "name": "wytiny", 14 | "email": "zjutiny@gmail.com" 15 | } 16 | ], 17 | "bugs": { 18 | "url": "https://github.com/Tinysymphony/react-native-drawer-menu/issues" 19 | }, 20 | "homepage": "https://github.com/Tinysymphony/react-native-drawer-menu#readme", 21 | "license": "MIT" 22 | } 23 | -------------------------------------------------------------------------------- /components/Grading/.npmignore: -------------------------------------------------------------------------------- 1 | example 2 | __tests__ 3 | .* 4 | -------------------------------------------------------------------------------- /components/Grading/GradingConstants.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by TinySymphony on 2016-12-26. 3 | * Constants 4 | */ 5 | 6 | export const COLOR = { 7 | ACTIVE_COLOR: '#fa952f', 8 | DEFAULT_COLOR: '#eee', 9 | DISABLE_COLOR: '#aaa', 10 | FONT_COLOR: '#999', 11 | UNDERLAY_COLOR: 'rgba(249, 246, 241, 0.31)' 12 | }; 13 | 14 | export const MODE = { 15 | BOARD: 'board', 16 | STARS: 'stars', 17 | SMILES: 'smiles', 18 | ARCS: 'arcs' 19 | }; 20 | 21 | /* eslint-disable max-len*/ 22 | export const SVG = { 23 | HAPPY: 'M511.99024 0.02c-282.294354 0-511.98976 229.695406-511.98976 511.98976 0 294.094118 229.695406 511.98976 511.98976 511.98976 282.394352 0 511.98976-217.895642 511.98976-511.98976C1023.98 229.715406 794.384592 0.02 511.99024 0.02zM701.886442 281.614368c36.699266 0 66.49867 29.799404 66.49867 66.49867s-29.799404 66.49867-66.49867 66.49867c-36.699266 0-66.49867-29.799404-66.49867-66.49867S665.187176 281.614368 701.886442 281.614368zM322.094038 281.614368c36.699266 0 66.49867 29.799404 66.49867 66.49867s-29.799404 66.49867-66.49867 66.49867-66.49867-29.799404-66.49867-66.49867C255.595368 311.413772 285.394772 281.614368 322.094038 281.614368zM693.086618 781.904362C648.087518 806.303874 588.688706 824.703506 524.689986 826.303474l0 0.299994-12.699746 0-12.799744 0L499.190496 826.303474c-63.898722-1.699966-123.297534-19.9996-168.296634-44.399112-58.99882-31.899362-87.598248-62.598748-87.598248-93.698126 0-22.299554 16.899662-39.699206 38.49923-39.699206 7.899842 0 15.599688 2.399952 22.299554 7.099858 5.599888 3.899922 11.199776 7.99984 17.099658 12.399752C338.693706 680.906382 356.693346 694.306114 380.49287 705.305894c31.49937 14.399712 76.99846 31.99936 131.597368 32.299354 54.49891-0.199996 99.998-17.799644 131.597368-32.299354 23.699526-10.899782 41.699166-24.299514 59.198816-37.299254 5.899882-4.399912 11.49977-8.49983 17.099658-12.399752 6.699866-4.699906 14.399712-7.099858 22.299554-7.099858 9.9998 0 19.799604 4.099918 26.99946 11.199776 7.399852 7.399852 11.49977 17.599648 11.49977 28.49943C780.684866 719.305614 751.98544 749.905002 693.086618 781.904362z', 24 | SAD: 'M701.952 281.6c36.864 0 66.56 29.696 66.56 66.56s-29.696 66.56-66.56 66.56-66.56-29.696-66.56-66.56C635.392 311.808 665.088 281.6 701.952 281.6zM512 0C229.888 0 0 229.888 0 512c0 294.4 229.888 512 512 512s512-217.6 512-512C1024 229.888 794.112 0 512 0zM322.048 281.6c36.864 0 66.56 29.696 66.56 66.56s-29.696 66.56-66.56 66.56-66.56-29.696-66.56-66.56C255.488 311.808 285.184 281.6 322.048 281.6zM769.024 779.776c-7.168 7.168-16.896 11.264-27.136 11.264-7.68 0-15.36-2.56-22.016-7.168-5.632-4.096-11.264-8.192-16.896-12.288-17.408-12.8-35.328-26.112-59.392-37.376-31.744-14.336-77.312-32.256-131.584-32.256-54.784 0-99.84 17.92-131.584 32.256-23.552 10.752-41.984 24.576-59.392 37.376-5.632 4.608-11.264 8.704-16.896 12.288-6.656 4.608-14.336 7.168-22.016 7.168-21.504 0-38.4-17.408-38.4-39.936 0-31.232 28.672-61.952 87.552-93.696 45.056-24.576 104.448-42.496 168.448-44.544l0 0 12.8 0 12.8 0 0 0.512c64 1.536 123.392 19.968 168.448 44.544 58.88 31.744 87.552 62.464 87.552 93.696C780.8 762.368 776.704 772.608 769.024 779.776z', 25 | STAR: 'M 0.000 10.000 L 11.756 16.180 L 9.511 3.090 L 19.021 -6.180 L 5.878 -8.090 L 0.000 -20.000 L -5.878 -8.090 L -19.021 -6.180 L -9.511 3.090 L -11.756 16.180 L 0.000 10.000' 26 | }; 27 | -------------------------------------------------------------------------------- /components/Grading/GradingModalStyle.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by TinySymphony on 2017-01-19. 3 | * Styles of GradingModal Component 4 | */ 5 | 6 | import {StyleSheet, Dimensions} from 'react-native'; 7 | const {width, height, scale} = Dimensions.get('window'); 8 | 9 | export const Size = { 10 | itemHeight: 40, 11 | widthFactor: 0.6, 12 | heightFactor: 0.4 13 | }; 14 | 15 | export const Color = { 16 | maskColor: '#00000077' 17 | }; 18 | 19 | // calculate offset number to place selected item at the center of the screen 20 | Size.offsetNum = Math.floor(height * Size.heightFactor / 2 / Size.itemHeight + 1); 21 | 22 | export default StyleSheet.create({ 23 | modalMask: { 24 | flex: 1, 25 | justifyContent: 'center', 26 | alignItems: 'center', 27 | backgroundColor: Color.maskColor 28 | }, 29 | modalContainer: { 30 | }, 31 | modal: { 32 | width: width * Size.widthFactor, 33 | overflow: 'hidden', 34 | backgroundColor: '#fff' 35 | }, 36 | modalItem: { 37 | height: Size.itemHeight, 38 | alignItems: 'center', 39 | justifyContent: 'center', 40 | borderBottomWidth: 2 / scale, 41 | borderBottomColor: '#bbb' 42 | }, 43 | selectedItem: { 44 | backgroundColor: '#e6f6f9' 45 | }, 46 | modalText: { 47 | fontSize: 18, 48 | color: '#999' 49 | }, 50 | selectedText: { 51 | fontSize: 22, 52 | color: '#333' 53 | }, 54 | modalButtons: { 55 | borderTopWidth: 2 / scale, 56 | borderColor: '#c6c6c6', 57 | flexDirection: 'row', 58 | justifyContent: 'space-around' 59 | }, 60 | modalButton: { 61 | height: 40, 62 | width: width * Size.widthFactor / 2, 63 | justifyContent: 'center', 64 | alignItems: 'center' 65 | }, 66 | buttonText: { 67 | fontSize: 18 68 | }, 69 | cancelButton: { 70 | backgroundColor: '#c7c7c7' 71 | }, 72 | confirmButton: { 73 | backgroundColor: '#49aec8' 74 | }, 75 | modalScroll: { 76 | height: height * Size.heightFactor 77 | }, 78 | buttonView: { 79 | flexDirection: 'row' 80 | }, 81 | cancelText: { 82 | color: '#fff' 83 | }, 84 | confirmText: { 85 | color: '#fff' 86 | } 87 | }); 88 | -------------------------------------------------------------------------------- /components/Grading/GradingStyle.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by TinySymphony on 2016-12-26. 3 | * Styles of Grading Component 4 | */ 5 | 6 | import {StyleSheet} from 'react-native'; 7 | 8 | export default StyleSheet.create({ 9 | board: { 10 | alignItems: 'center', 11 | padding: 4, 12 | width: 70, 13 | height: 80, 14 | borderRadius: 4, 15 | borderWidth: 0.5, 16 | borderColor: '#ccc' 17 | }, 18 | boardGradingWp: { 19 | alignItems: 'center', 20 | width: 62, 21 | paddingBottom: 2, 22 | borderBottomWidth: 0.5, 23 | borderBottomColor: '#ccc' 24 | }, 25 | boardGrading: { 26 | fontSize: 24, 27 | color: '#fa952f' 28 | }, 29 | boardNum: { 30 | color: '#999' 31 | }, 32 | boardStars: { 33 | flexDirection: 'row', 34 | justifyContent: 'center', 35 | marginTop: 4 36 | }, 37 | stars: { 38 | flexDirection: 'row', 39 | justifyContent: 'center' 40 | }, 41 | arcs: { 42 | // flexDirection: 'row', 43 | // justifyContent: 'center', 44 | // alignItems: 'flex-start' 45 | }, 46 | arcContainer: { 47 | alignItems: 'center' 48 | }, 49 | arc: { 50 | alignItems: 'center', 51 | justifyContent: 'center' 52 | }, 53 | arcGrading: { 54 | flexDirection: 'row', 55 | justifyContent: 'center' 56 | }, 57 | smiles: { 58 | flexDirection: 'row', 59 | justifyContent: 'space-around' 60 | } 61 | }); 62 | -------------------------------------------------------------------------------- /components/Grading/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 鲜果FE 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, 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, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /components/Grading/__tests__/Grading.test.js: -------------------------------------------------------------------------------- 1 | import 'react-native'; 2 | import React from 'react'; 3 | import {shallow} from 'enzyme'; 4 | 5 | import Grading from '../index.js'; 6 | import GradingModal from '../GradingModal.js'; 7 | 8 | // Note: test renderer must be required after react-native. 9 | import renderer from 'react-test-renderer'; 10 | 11 | it('renders grading modal correctly', () => { 12 | expect(renderer.create( 13 | 18 | )).toMatchSnapshot(); 19 | }); 20 | 21 | it('renders board correctly', () => { 22 | const tree = shallow( 23 | 24 | ); 25 | let instance = tree.instance(); 26 | expect(instance.props.score).toEqual(4); 27 | expect(instance.props.scoreBase).toEqual(5); 28 | expect(instance.props.num).toEqual(72346); 29 | expect(instance.props.fontColor).toEqual('#552da6'); 30 | expect(instance.props.activeColor).toEqual('#2bb8aa'); 31 | expect(instance.props.defaultColor).toEqual('#eee'); 32 | expect(instance.props.cancelText).toEqual('Cancel'); 33 | expect(instance.props.confirmText).toEqual('Confirm'); 34 | }); 35 | 36 | it('renders stars correctly', () => { 37 | const tree = shallow( 38 | 39 | ); 40 | let instance = tree.instance(); 41 | expect(instance.props.score).toEqual(4); 42 | expect(instance.props.activeColor).toEqual('#a52ca6'); 43 | }); 44 | 45 | it('renders arcs correctly', () => { 46 | const tree = shallow( 47 | 48 | ); 49 | let instance = tree.instance(); 50 | expect(instance.props.score).toEqual(6); 51 | expect(instance.props.scoreBase).toEqual(8); 52 | expect(instance.props.defaultColor).toEqual('#999'); 53 | }); 54 | 55 | it('renders smiles correctly', () => { 56 | const tree = shallow( 57 | 58 | ); 59 | let instance = tree.instance(); 60 | expect(instance.props.isLike).toEqual(true); 61 | expect(instance.props.activeColor).toEqual('#556'); 62 | }); 63 | 64 | it('interact with modal', () => { 65 | let resultScore; 66 | let initScore = 38; 67 | const tree = shallow( 68 | {resultScore = score;}}/> 73 | ); 74 | let instance = tree.instance(); 75 | instance.onPressCancel(); 76 | expect(instance.isModalVisible).toEqual(false); 77 | instance.openModal(); 78 | instance.onScrollChange(240, 1000); 79 | expect(instance.isModalVisible).toEqual(true); 80 | instance.onPressConfirm(); 81 | expect(instance.isModalVisible).toEqual(false); 82 | expect(resultScore).toEqual(initScore); 83 | }); 84 | -------------------------------------------------------------------------------- /components/Input/.npmignore: -------------------------------------------------------------------------------- 1 | example/ 2 | __tests__/ 3 | .* 4 | components/ 5 | coverage/ 6 | index.android.js 7 | index.ios.js 8 | android/ 9 | ios/ 10 | -------------------------------------------------------------------------------- /components/Input/InputStyle.js: -------------------------------------------------------------------------------- 1 | import StyleSheet from 'react-native-stylesheet-xg'; 2 | 3 | const Style = StyleSheet.create({ 4 | inputCon: { 5 | flexDirection: 'row', 6 | alignItems: 'center', 7 | height: 45, 8 | paddingLeft: 10, 9 | paddingRight: 10, 10 | borderBottomWidth: 1, 11 | borderBottomColor: '#e5e5e5' 12 | }, 13 | multiInputCon: { 14 | height: null, 15 | flexDirection: 'column', 16 | alignSelf: 'stretch' 17 | }, 18 | focus: { 19 | borderColor: '#ff9900' 20 | }, 21 | error: { 22 | borderColor: '#ec5330' 23 | }, 24 | disabled: { 25 | backgroundColor: '#e5e5e5' 26 | }, 27 | input: { 28 | flexGrow: 1, 29 | height: 44, 30 | padding: 0, 31 | color: '#333', 32 | fontSize: 14 33 | }, 34 | columnModeInput: { 35 | marginTop: -10, 36 | marginBottom: -5, 37 | alignSelf: 'stretch' 38 | }, 39 | multiInput: { 40 | marginBottom: -20, 41 | textAlignVertical: 'top', 42 | alignSelf: 'stretch', 43 | android: { 44 | paddingTop: 8 45 | }, 46 | ios: { 47 | marginTop: -3, 48 | marginBottom: -28 49 | } 50 | }, 51 | labelCon: { 52 | flexDirection: 'row', 53 | width: 90, 54 | height: 44, 55 | alignItems: 'center', 56 | justifyContent: 'flex-start' 57 | }, 58 | columnModeLabelCon: { 59 | width: null, 60 | height: 35, 61 | alignSelf: 'stretch' 62 | }, 63 | label: { 64 | fontSize: 14, 65 | color: '#666' 66 | }, 67 | lineBottom: { 68 | position: 'absolute', 69 | height: 2, 70 | bottom: -1, 71 | left: 0, 72 | right: 0, 73 | backgroundColor: '#ff9900' 74 | }, 75 | lineError: { 76 | backgroundColor: '#ec5330' 77 | }, 78 | tips: { 79 | marginTop: 1, 80 | marginLeft: 5, 81 | fontSize: 12, 82 | color: '#06c1ae' 83 | }, 84 | required: { 85 | fontSize: 14, 86 | color: '#ec5330' 87 | } 88 | }); 89 | 90 | export default Style; 91 | -------------------------------------------------------------------------------- /components/Input/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 鲜果FE 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, 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, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /components/Input/README.md: -------------------------------------------------------------------------------- 1 | ### The react-native-input-xg 2 | * react native Input component for both Android and iOS based on pure JavaScript 3 | 4 | ### Main 5 | * This component provide some more functions besides the basic input RN provided 6 | 7 | ### Properties 8 | * Besides the basic properties RN provided, we also provide belows: 9 | 10 | ![image](https://raw.githubusercontent.com/lulutia/images/master/react-native-components/Screen-Capture-39.gif) 11 | 12 | ### Properties 13 | 14 | | Prop | Default | Type | Description | 15 | | :------------ |:---------------:| :---------------:| :-----| 16 | | label | undefined | `string` | Specify the label of the input | 17 | | defaultValue | undefined | `string` | Specify the default value of the input | 18 | | editable | true | `bool` | if you can edit the input| 19 | | multiline | false | `bool` | if the input support the multiline| 20 | | error | false | `bool` | for you to judge if the content is wrong | 21 | | required| false | `bool` | give you an indicate to show this one is a must | 22 | | tips | undefined | `string` | give some more explanation | 23 | | wrapperStyle | - | `style` | Specify the wrapper style | 24 | | focusStyle | - | `style` | Specify the style when focus | 25 | | disabledStyle | - | `style` | Specify the style when disabled| 26 | | errorStyle | - | `style` | Specify the style when there's some error| 27 | | labelStyle | - | `style` | Specify the label style| 28 | | initJudge | true | `bool` | if judge error when init| 29 | | readOnly | false | `bool` | you can only see but can not operate| 30 | -------------------------------------------------------------------------------- /components/Input/__tests__/__snapshots__/Input.test.js.snap: -------------------------------------------------------------------------------- 1 | exports[`undefined 1`] = ` 2 | 26 | 54 | 70 | 71 | `; 72 | -------------------------------------------------------------------------------- /components/Input/example/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Sample React Native App 3 | * https://github.com/facebook/react-native 4 | * @flow 5 | */ 6 | 7 | import React, {Component} from 'react'; 8 | import { 9 | AppRegistry, 10 | StyleSheet, 11 | Text, 12 | View 13 | } from 'react-native'; 14 | import Input from '../Input'; 15 | 16 | export default class input extends Component { 17 | 18 | constructor(props) { 19 | super(props); 20 | this.state = { 21 | test1: '', 22 | test2: '12', 23 | test3: '', 24 | test4: '', 25 | test5: '', 26 | test6: '', 27 | test7: '' 28 | }; 29 | } 30 | render() { 31 | return ( 32 | 33 | { 34 | console.debug('trsy'); 35 | this.setState({test1: text}); 36 | }}/> 37 | 38 | 39 | { 40 | this.setState({test3: text}); 41 | }}/> 42 | { 43 | this.setState({test4: text}); 44 | }}/> 45 | { 46 | this.setState({test5: text}); 47 | }}/> 48 | { 49 | this.setState({test6: text}); 50 | }}/> 51 | { 56 | this.setState({test7: text}); 57 | }}/> 58 | 59 | ); 60 | } 61 | } 62 | 63 | const styles = StyleSheet.create({ 64 | container: { 65 | backgroundColor: '#fff' 66 | }, 67 | welcome: { 68 | fontSize: 20, 69 | textAlign: 'center', 70 | margin: 10 71 | }, 72 | instructions: { 73 | textAlign: 'center', 74 | color: '#333333', 75 | marginBottom: 5 76 | } 77 | }); 78 | -------------------------------------------------------------------------------- /components/Input/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-input-xg", 3 | "version": "0.0.2", 4 | "description": "react native input component for both Android and IOS, useing pure JavaScript", 5 | "main": "Input.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/xgfe/react-native-ui-xg.git" 9 | }, 10 | "keywords": [ 11 | "react-native", 12 | "input", 13 | "react-native-input" 14 | ], 15 | "author": "xgfe", 16 | "license": "MIT", 17 | "bugs": { 18 | "url": "https://github.com/xgfe/react-native-ui-xg/issues" 19 | }, 20 | "homepage": "https://github.com/xgfe/react-native-ui-xg/components/Input#readme", 21 | "dependencies": { 22 | "react-native-stylesheet-xg": "^1.1.0" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /components/LabelSelect/.npmignore: -------------------------------------------------------------------------------- 1 | example 2 | __tests__ 3 | .* 4 | -------------------------------------------------------------------------------- /components/LabelSelect/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 鲜果FE 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, 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, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /components/LabelSelect/LabelSelectStyle.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by TinySymphony on 2017-01-03. 3 | */ 4 | 5 | import {Dimensions, StyleSheet} from 'react-native'; 6 | const window = Dimensions.get('window'); 7 | const {width, height, scale} = window; 8 | 9 | export const Color = { 10 | disableColor: '#eaeaea', 11 | main: '#40cca2' 12 | }; 13 | 14 | export const IMG = { 15 | closeIcon: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABnElEQVRYR8WXy1HDMBCG/734Sjoh6QAqgBKgg/gij29wtC4uAegAKoASXEJKCFfPeMTIYxn5IVmvTHJM4v0+rbS7MuHKH7oyH6NAXde7tm3fpBARvTLGmpRynPM9gD4+gGcVfxTgnH8CeBj+cAZwn0pigH8D2A3xG8bYoV+sWuVMQH6dRGIFLmN/McYe5wJ7IcQPEd1oqY+SWIMLIX6J6G6xBRIqH0gl4QKfZEDbimgJV/iqQGwmfOBGgVAJX7hVwFciBL4p4CoRCncS2JIYDq/eZDAvNVtHdZ4FlhKV8VWH84I7Z2CjRMcF+qxcPeScgS2JELh3BtR5ADDZ85gB5pUBw2DRz5j37HAWMJVan8aIAeYkYKtzKRAzwDYFXJpMzBS1CrjAY6eoUcAHHiOxKhACD5VYCMTAQyQmAingvhL6rVje24On2trEM1VH13WHsixPk1ZcVVVDRLcqUGhvn4sYJJbXcl0gFdy0HUKIj6IoniYZGEzfiUj282OqtyJdAsCLEOKcZdkxz3PJ+X8zst1aLvnbZiu+JFzG/gPiB7Awgm9hrgAAAABJRU5ErkJggg==', 16 | addIcon: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA7ElEQVRYR+2X0QnCQAyG87cLuIF1EusEOoq+NPTJ+lSuLzqKTmDdRDdwgbvISRVEhGuVFiGBe8td/nyB+wlo4MDA9amzgLIskyiKjr4B59wsz/Nzl2Y6CzDGLAFsfVERWTHzrm8BBYB1I2DDzIUKUAJKQAn8NwH/t8dxPAcwCulERFIi8sdHDaAOvHe11h4e3vH0gqqqvJmMQx75NkdEzsw88e8MIoCILlmWJS8CGntdEFHQCAB4/NOGxklEgkZARFfn3P5tBG2xGmPUDZWAElACSmDYxaSx7/v/b61Ne1/N2nrHp/zOu+GvBNwAa6vsIVXzFTsAAAAASUVORK5CYII=' 17 | }; 18 | 19 | export default StyleSheet.create({ 20 | selectedView: { 21 | flexDirection: 'row', 22 | justifyContent: 'flex-start', 23 | alignItems: 'center', 24 | flexWrap: 'wrap' 25 | }, 26 | selectedItem: { 27 | margin: 4, 28 | borderWidth: 2 / scale, 29 | borderRadius: 6, 30 | borderColor: '#aaa', 31 | flexDirection: 'row', 32 | justifyContent: 'center', 33 | alignItems: 'center', 34 | overflow: 'hidden', 35 | backgroundColor: '#f6f6f6' 36 | }, 37 | addItem: { 38 | padding: 7 39 | }, 40 | disableColor: { 41 | backgroundColor: Color.disableColor 42 | }, 43 | labelText: { 44 | padding: 6, 45 | fontSize: 14, 46 | lineHeight: 14, 47 | maxWidth: 300 48 | }, 49 | closeContainer: { 50 | padding: 8, 51 | borderLeftWidth: 2 / scale, 52 | borderLeftColor: '#c8c8c8' 53 | }, 54 | closeIcon: { 55 | width: 10, 56 | height: 10 57 | }, 58 | addIcon: { 59 | width: 12, 60 | height: 12 61 | }, 62 | modalMask: { 63 | flex: 1, 64 | justifyContent: 'center', 65 | alignItems: 'center', 66 | backgroundColor: '#00000077' 67 | }, 68 | modalContainer: {}, 69 | modal: { 70 | height: height * 0.6, 71 | width: width * 0.6, 72 | overflow: 'hidden', 73 | borderRadius: 10, 74 | backgroundColor: '#fff' 75 | }, 76 | title: { 77 | paddingHorizontal: 20, 78 | paddingVertical: 10, 79 | borderBottomWidth: 2 / scale, 80 | borderBottomColor: '#bbb' 81 | }, 82 | titleText: { 83 | fontSize: 18, 84 | lineHeight: 20 85 | }, 86 | scrollView: { 87 | height: height * 0.6 - 80 88 | }, 89 | buttonView: { 90 | borderBottomLeftRadius: 10, 91 | borderBottomRightRadius: 10, 92 | flexDirection: 'row', 93 | justifyContent: 'space-around' 94 | }, 95 | modalButton: { 96 | height: 40, 97 | width: width * 0.3, 98 | paddingLeft: 20, 99 | paddingRight: 20, 100 | justifyContent: 'center', 101 | alignItems: 'center', 102 | backgroundColor: Color.main 103 | }, 104 | modalItem: { 105 | height: 50, 106 | paddingHorizontal: 20, 107 | flexDirection: 'row', 108 | justifyContent: 'space-between', 109 | alignItems: 'center', 110 | borderBottomWidth: 2 / scale, 111 | borderBottomColor: '#bbb' 112 | }, 113 | modalText: { 114 | fontSize: 16, 115 | width: width * 0.6 - 70 116 | }, 117 | buttonText: { 118 | color: '#fff', 119 | fontSize: 16 120 | }, 121 | confirmButton: { 122 | borderLeftWidth: 2 / scale, 123 | borderLeftColor: '#fff' 124 | }, 125 | outerCircle: { 126 | borderWidth: 2 / scale, 127 | borderColor: '#888', 128 | width: 20, 129 | height: 20, 130 | borderRadius: 10, 131 | overflow: 'hidden', 132 | justifyContent: 'center', 133 | alignItems: 'center' 134 | }, 135 | enableCircle: { 136 | borderColor: Color.main 137 | }, 138 | innerCircle: { 139 | backgroundColor: Color.main, 140 | width: 16, 141 | height: 16, 142 | borderRadius: 8, 143 | overflow: 'hidden' 144 | }, 145 | disableText: { 146 | color: '#999' 147 | } 148 | }); 149 | -------------------------------------------------------------------------------- /components/LabelSelect/README.md: -------------------------------------------------------------------------------- 1 | ## react-native-label-select [![Build Status](https://travis-ci.org/xgfe/react-native-label-select.svg?branch=master)](https://travis-ci.org/xgfe/react-native-label-select) [![Coverage Status](https://coveralls.io/repos/github/Tinysymphony/react-native-label-select/badge.svg?branch=master)](https://coveralls.io/github/Tinysymphony/react-native-label-select?branch=master) 2 | LabelSelect is a component used for making multiple choices. The modal is a checkbox like html. 3 | 4 | ## Example 5 | 6 | 7 | 8 | 9 | ## Usage 10 | 11 | ```shell 12 | npm install --save react-native-label-select 13 | ``` 14 | 15 | ```js 16 | import LabelSelect from 'react-native-label-select'; 17 | ``` 18 | 19 | ```html 20 | {...}}> 28 | 29 | selected ItemA 33 | Item B 36 | 37 | 38 | ``` 39 | 40 | ## Properties 41 | 42 | **LabelSelect** 43 | 44 | | Prop | Default | Type | Description | 45 | | --- | --- | --- | --- | 46 | | style | - | object | Specify styles for the LabelSelect | 47 | | title | - | string | The title text of the modal | 48 | | readOnly | false | bool | is the component readonly | 49 | | enable | true | bool | is the component interactive | 50 | | enableAddBtn | true | bool | whether to show the add button | 51 | | onConfirm | - | function | Triggered when the confirm button of modal is pressed with the newly selected items list passed as the only argument | 52 | | confirmText | - | string | Text of confirm button. | 53 | | cancelText | - | string | Text of cancelText button. | 54 | | customStyle | - | object | You can customize styles of `modal` / `buttonView` / `confirmButton` / `confirmText` / `cancelButton` / `cancelText` by `customStyle. | 55 | 56 | **LabelSelect.Label** 57 | 58 | 59 | | Prop | Default | Type | Description | 60 | | --- | --- | --- | --- | 61 | | onCancel | - | function | Triggered when the close button of Label is pressed. | 62 | | data | - | any | Data that bind to the Label | 63 | | customStyle | - | object | You can customize styles of `text` by `customStyle. | 64 | 65 | **LabelSelect.ModalItem** 66 | 67 | 68 | 69 | 70 | | Prop | Default | Type | Description | 71 | | --- | --- | --- | --- | 72 | | data | - | any | Data that bind to the ModalItem. After confirming the items selected on modal, the data will be passed to the selected list. | 73 | 74 | 75 | ## Instance Methods 76 | 77 | 78 | | Method | Params | Description | 79 | | --- | --- | --- | 80 | | openModal | - | Open select modal | 81 | | cancelSelect | - | Close select modal. Also triggered when the cancel button of modal being pressed. | 82 | | customStyle | - | object | You can customize styles of `modalText` / `outerCircle` / `innerCircle` by `customStyle. | 83 | 84 | Use `ref` property as a hook to invoke internal methods. 85 | 86 | ```html 87 | ... 88 | ``` 89 | 90 | ```js 91 | this.ref.select.openModal() 92 | this.ref.select.cancelSelect() 93 | ``` 94 | -------------------------------------------------------------------------------- /components/LabelSelect/__tests__/LabelSelect.test.js: -------------------------------------------------------------------------------- 1 | import 'react-native'; 2 | import React from 'react'; 3 | import {shallow} from 'enzyme'; 4 | import renderer from 'react-test-renderer'; 5 | 6 | import LabelSelect from '../index'; 7 | 8 | import mock from './__mock__/mock'; 9 | 10 | const {Label, ModalItem} = LabelSelect; 11 | 12 | let selectedItems = mock.selectedList.map((item, index) => 13 | 19 | ); 20 | 21 | let otherItems = mock.list.map((item, index) => 22 | 25 | {item.text} 26 | 27 | ); 28 | 29 | // snapshot test 30 | 31 | it('renders enabled LabelSelect', () => { 32 | let tree = renderer.create( 33 | {}} 36 | > 37 | {selectedItems} 38 | {otherItems} 39 | 40 | ).toJSON(); 41 | expect(tree).toMatchSnapshot(); 42 | }); 43 | 44 | it('renders readOnly LabelSelect', () => { 45 | let tree = renderer.create( 46 | {}} 50 | > 51 | {selectedItems} 52 | {otherItems} 53 | 54 | ).toJSON(); 55 | expect(tree).toMatchSnapshot(); 56 | }); 57 | 58 | it('renders disabled LabelSelect', () => { 59 | let tree = renderer.create( 60 | {}} 64 | > 65 | {selectedItems} 66 | {otherItems} 67 | 68 | ).toJSON(); 69 | expect(tree).toMatchSnapshot(); 70 | }); 71 | 72 | it('renders a modal item', () => { 73 | let item = mock.list[0]; 74 | expect(renderer.create( 75 | {item.text} 76 | )).toMatchSnapshot(); 77 | }); 78 | 79 | // enzyme test 80 | 81 | it('interact with modal', () => { 82 | let arr = []; 83 | const item = mock.list[0]; 84 | const tree = shallow( 85 | {arr = list;}} 88 | enableAddBtn={true} 89 | > 90 | {selectedItems} 91 | {otherItems} 92 | 93 | ); 94 | let select = tree.instance(); 95 | expect(tree.find('TouchableHighlight').length).toEqual(4); 96 | select.openModal(); 97 | expect(tree.state('isModalVisible')).toEqual(true); 98 | select.toggleSelect(item); 99 | select.confirmSelect(); 100 | expect(arr[0]).toEqual(item); 101 | expect(tree.state('isModalVisible')).toEqual(false); 102 | select.openModal(); 103 | expect(tree.state('isModalVisible')).toEqual(true); 104 | select.cancelSelect(); 105 | expect(tree.state('isModalVisible')).toEqual(false); 106 | select.confirmSelect(); 107 | }); 108 | 109 | it('selecte a item', () => { 110 | let data = mock.list[0]; 111 | let result; 112 | const tree = shallow( 113 | {result = item;}} 116 | > 117 | {data.text} 118 | 119 | ); 120 | let instance = tree.instance(); 121 | instance._toggleSelect(); 122 | expect(result).toEqual(data); 123 | }); 124 | -------------------------------------------------------------------------------- /components/LabelSelect/__tests__/__mock__/mock.json: -------------------------------------------------------------------------------- 1 | { 2 | "selectedList": [{ 3 | "text": "A" 4 | }, { 5 | "text": "B" 6 | }], 7 | "list": [{ 8 | "text": "C" 9 | }, { 10 | "text": "D" 11 | }] 12 | } 13 | -------------------------------------------------------------------------------- /components/LabelSelect/example/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by TinySymphony on 2017-01-03. 3 | */ 4 | 5 | import React, {Component} from 'react'; 6 | import { 7 | View, 8 | Text, 9 | StyleSheet 10 | } from 'react-native'; 11 | import LabelSelect from '../index'; 12 | 13 | export default class checkbox extends Component { 14 | constructor(props) { 15 | super(props); 16 | this.state = { 17 | arr: [{ 18 | name: 'Aspirin', 19 | isSelected: false, 20 | value: 1 21 | }, { 22 | name: 'MarginTop', 23 | isSelected: true, 24 | value: 2 25 | }, { 26 | name: 'Dooper', 27 | isSelected: true, 28 | value: 3 29 | }, { 30 | name: 'Young Skywalker', 31 | isSelected: false, 32 | value: 4 33 | }, { 34 | name: 'Jedi Master', 35 | isSelected: true, 36 | value: 5 37 | }, { 38 | name: 'Anakin', 39 | isSelected: false, 40 | value: 6 41 | }, { 42 | name: 'ナウシカ', 43 | isSelected: false, 44 | value: 7 45 | }, { 46 | name: '你好', 47 | isSelected: false, 48 | value: 8 49 | }] 50 | }; 51 | this.selectConfirm = this.selectConfirm.bind(this); 52 | this.deleteItem = this.deleteItem.bind(this); 53 | } 54 | selectConfirm(list) { 55 | let {arr} = this.state; 56 | for (let item of list) { 57 | let index = arr.findIndex(ele => ele === item); 58 | if (~index) {arr[index].isSelected = true;} 59 | else {continue;} 60 | } 61 | this.setState({arr: arr}); 62 | } 63 | deleteItem(item) { 64 | let {arr} = this.state; 65 | let index = arr.findIndex(a => a === item); 66 | arr[index].isSelected = false; 67 | this.setState({arr: arr}); 68 | } 69 | render() { 70 | return ( 71 | 72 | Normal LabelSelect 73 | 79 | {this.state.arr.filter(item => item.isSelected).map((item, index) => 80 | {this.deleteItem(item);}} 84 | >{item.name} 85 | )} 86 | {this.state.arr.filter(item => !item.isSelected).map((item, index) => 87 | {item.name} 91 | )} 92 | 93 | ReadOnly LabelSelect 94 | 100 | {this.state.arr.filter(item => item.isSelected).map((item, index) => 101 | {this.deleteItem(item);}} 105 | >{item.name} 106 | )} 107 | 108 | Disabled LabelSelect 109 | 115 | {this.state.arr.filter(item => item.isSelected).map((item, index) => 116 | {this.deleteItem(item);}} 120 | >{item.name} 121 | )} 122 | 123 | 124 | ); 125 | } 126 | } 127 | 128 | const styles = StyleSheet.create({ 129 | container: { 130 | flex: 1, 131 | padding: 10, 132 | justifyContent: 'center', 133 | alignItems: 'flex-start' 134 | }, 135 | labelSelect: { 136 | marginTop: 5, 137 | marginBottom: 20, 138 | padding: 5, 139 | borderWidth: 1, 140 | borderRadius: 6, 141 | borderStyle: 'dashed', 142 | borderColor: '#999' 143 | }, 144 | text: { 145 | fontSize: 16, 146 | color: '#999' 147 | } 148 | }); 149 | -------------------------------------------------------------------------------- /components/LabelSelect/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-label-select", 3 | "version": "1.0.10", 4 | "description": "A label select component for React Native apps", 5 | "keywords": [ 6 | "label", 7 | "select", 8 | "react-native", 9 | "react" 10 | ], 11 | "main": "./index.js", 12 | "author": "xgfe", 13 | "maintainers": [ 14 | { 15 | "name": "wytiny", 16 | "email": "zjutiny@gmail.com" 17 | } 18 | ], 19 | "bugs": { 20 | "url": "https://github.com/Tinysymphony/react-native-label-select/issues" 21 | }, 22 | "homepage": "https://github.com/Tinysymphony/react-native-label-select#readme", 23 | "license": "MIT" 24 | } 25 | -------------------------------------------------------------------------------- /components/Link/.npmignore: -------------------------------------------------------------------------------- 1 | example/ 2 | __tests__/ 3 | .* 4 | components/ 5 | coverage/ 6 | index.android.js 7 | index.ios.js 8 | android/ 9 | ios/ 10 | -------------------------------------------------------------------------------- /components/Link/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 鲜果FE 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, 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, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /components/Link/Link.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import { 3 | View, 4 | Text, 5 | Image, 6 | TouchableHighlight 7 | } from 'react-native'; 8 | import Style, {IMG} from './LinkStyle'; 9 | 10 | class Link extends Component { 11 | 12 | skipIcon = { 13 | uri: IMG.skipIcon 14 | } 15 | 16 | // 构造 17 | constructor(props) { 18 | super(props); 19 | 20 | this.renderLabel = this.renderLabel.bind(this); 21 | } 22 | 23 | renderLabel(isColumnMode) { 24 | const {label, labelStyle, tips, value, placeholder, required} = this.props; 25 | 26 | if (typeof label === 'undefined') { 27 | return; 28 | } 29 | return ( 30 | 31 | {required && *}{label} 32 | {!!tips && {tips}} 33 | {isColumnMode && 34 | } 39 | 40 | ); 41 | } 42 | 43 | renderValue(isColumnMode) { 44 | const {value, placeholder} = this.props; 45 | 46 | if (!value && !placeholder) { 47 | return; 48 | } 49 | 50 | const valueStyles = [Style.input]; 51 | 52 | if (placeholder && !value) { 53 | valueStyles.push({color: '#ccc'}); 54 | } 55 | 56 | if (isColumnMode) { 57 | valueStyles.push(Style.columnModeInput); 58 | } 59 | 60 | return {value || placeholder}; 61 | } 62 | 63 | render() { 64 | const { 65 | multiline, 66 | error, 67 | wrapperStyle, 68 | errorStyle, 69 | label, 70 | tips, 71 | onPress, 72 | disabled 73 | } = this.props; 74 | 75 | const isColumnMode = multiline || !!tips; 76 | 77 | return ( 78 | 79 | 86 | {this.renderLabel(isColumnMode)} 87 | {this.renderValue(isColumnMode)} 88 | {isColumnMode || 89 | } 94 | {error && } 95 | 96 | 97 | ); 98 | } 99 | } 100 | 101 | Link.defaultProps = { 102 | multiline: false, 103 | error: false, 104 | disabled: false 105 | }; 106 | 107 | Link.propTypes = { 108 | label: React.PropTypes.string, 109 | value: React.PropTypes.string, 110 | error: React.PropTypes.bool, 111 | required: React.PropTypes.bool, 112 | tips: React.PropTypes.string, 113 | wrapperStyle: React.PropTypes.object, 114 | errorStyle: React.PropTypes.object, 115 | labelStyle: React.PropTypes.object, 116 | onPress: React.PropTypes.func 117 | }; 118 | 119 | 120 | export default Link; 121 | -------------------------------------------------------------------------------- /components/Link/README.md: -------------------------------------------------------------------------------- 1 | ### The react-native-link-xg 2 | * react native Link component for both Android and iOS based on pure JavaScript 3 | 4 | ### Main 5 | * This component provide a Link function for you with which you can handle your own routers 6 | 7 | ### Properties 8 | link 9 | ![image](https://raw.githubusercontent.com/lulutia/images/master/react-native-components/Screen-Capture-41.gif) 10 | 11 | ### Properties 12 | 13 | | Prop | Default | Type | Description | 14 | | :------------ |:---------------:| :---------------:| :-----| 15 | | label | undefined | `string` | Specify the label of the link | 16 | | value | - | `string` | Specify the value of the link | 17 | | disabled | false | `bool` | if you can link | 18 | | multiline | false | `bool` | if the link support the multiline| 19 | | error | false | `bool` | for you to judge if the content is wrong | 20 | | required| false | `bool` | give you an indicate to show this one is a must | 21 | | tips | undefined | `string` | give some more explanation | 22 | | wrapperStyle | - | `style` | Specify the wrapper style | 23 | | errorStyle | - | `style` | Specify the style when there's some error| 24 | | labelStyle | - | `style` | Specify the label style| 25 | | onPress | - | `func` | you can do sth when you press| 26 | -------------------------------------------------------------------------------- /components/Link/__tests__/Link.test.js: -------------------------------------------------------------------------------- 1 | import {jsdom} from 'jsdom'; 2 | global.document = jsdom(''); 3 | global.window = document.defaultView; 4 | import React, {Component, propTypes} from 'react'; 5 | import { 6 | Platform, 7 | View, 8 | Text, 9 | TextInput, 10 | Animated, 11 | TouchableWithoutFeedback 12 | } from 'react-native'; 13 | import renderer from 'react-test-renderer'; 14 | import {shallow, mount} from 'enzyme'; 15 | import Link from '../Link'; 16 | 17 | console.error = function () {}; 18 | 19 | describe('test node', () => { 20 | it('check node number', () => { 21 | const wrapper = mount(); 22 | expect(wrapper.find(Animated.View).length).toEqual(0); 23 | expect(wrapper.find(TextInput).length).toEqual(0); 24 | }); 25 | }); 26 | 27 | describe('test props', () => { 28 | it('check default props', () => { 29 | const wrapper = mount( 30 | ); 31 | expect(wrapper.prop('multiline')).toEqual(false); 32 | expect(wrapper.prop('error')).toEqual(false); 33 | expect(wrapper.prop('disabled')).toEqual(false); 34 | }); 35 | 36 | it('check props', () => { 37 | const wrapper1 = mount( 38 | ); 42 | expect(wrapper1.prop('label')).toEqual('age'); 43 | expect(wrapper1.prop('tips')).toEqual("can't fix"); 44 | }); 45 | }); 46 | 47 | describe('test branch', () => { 48 | 49 | 50 | it('check require', () => { 51 | const wrapper1 = mount( 52 | 56 | ); 57 | const wrapper2 = mount( 58 | 62 | ); 63 | expect(wrapper1.find(Text).length).toEqual(1); 64 | expect(wrapper2.find(Text).length).toEqual(2); 65 | }); 66 | 67 | it('check tips', () => { 68 | const wrapper3 = mount( 69 | 72 | ); 73 | const wrapper4 = mount( 74 | 79 | ); 80 | expect(wrapper3.find(Text).length).toEqual(1); 81 | expect(wrapper4.find(Text).length).toEqual(3); 82 | }); 83 | 84 | it('check error', () => { 85 | const wrapper5 = mount( 86 | 91 | ); 92 | expect(wrapper5.find(View).length).toEqual(4); 93 | }); 94 | }); 95 | 96 | describe('check function', () => { 97 | 98 | }); 99 | -------------------------------------------------------------------------------- /components/Link/example/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Sample React Native App 3 | * https://github.com/facebook/react-native 4 | * @flow 5 | */ 6 | 7 | import React, {Component} from 'react'; 8 | import { 9 | StyleSheet, 10 | Text, 11 | View 12 | } from 'react-native'; 13 | import Link from '../Link'; 14 | 15 | export default class link extends Component { 16 | 17 | constructor(props) { 18 | super(props); 19 | } 20 | render() { 21 | return ( 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | ); 31 | } 32 | } 33 | 34 | const styles = StyleSheet.create({ 35 | container: { 36 | flex: 1, 37 | justifyContent: 'center' 38 | }, 39 | welcome: { 40 | fontSize: 20, 41 | textAlign: 'center', 42 | margin: 10 43 | }, 44 | instructions: { 45 | textAlign: 'center', 46 | color: '#333333', 47 | marginBottom: 5 48 | } 49 | }); 50 | 51 | -------------------------------------------------------------------------------- /components/Link/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-link-xg", 3 | "version": "0.0.1", 4 | "description": "react native link component for both Android and IOS, using pure JavaScript", 5 | "main": "Link.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/xgfe/react-native-ui-xg.git" 9 | }, 10 | "keywords": [ 11 | "react-native", 12 | "link", 13 | "react-native-link" 14 | ], 15 | "author": "xgfe", 16 | "license": "MIT", 17 | "bugs": { 18 | "url": "https://github.com/xgfe/react-native-ui-xg/issues" 19 | }, 20 | "homepage": "https://github.com/xgfe/react-native-ui-xg/components/Link#readme", 21 | "dependencies": { 22 | "react-native-stylesheet-xg": "^1.1.0" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /components/PressMenu/.npmignore: -------------------------------------------------------------------------------- 1 | example 2 | __tests__ 3 | .* 4 | -------------------------------------------------------------------------------- /components/PressMenu/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 鲜果FE 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, 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, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /components/PressMenu/README.md: -------------------------------------------------------------------------------- 1 | ## react-native-press-menu 2 | 3 | PressMenu component for React Native Application (ios / android). 4 | This component reacts to user's long press action on hooked UI View and offers a customizable menu, inspired by Pinterest's interaction. 5 | 6 | 7 | ### Examples 8 | 9 | 10 | ### Usage 11 | 12 | **install from npm** 13 | 14 | ``` shell 15 | npm install --save react-native-press-menu 16 | ``` 17 | 18 | **import in project** 19 | 20 | ``` js 21 | import PressMenu from 'react-native-press-menu'; 22 | ``` 23 | 24 | ## Properties 25 | 26 | ### Instance methods 27 | 28 | LICENSE MIT 29 | -------------------------------------------------------------------------------- /components/PressMenu/__tests__/test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by TinySymphony on 2017-04-10. 3 | */ 4 | 5 | /* eslint-disable */ 6 | 7 | import { 8 | View 9 | } from 'react-native'; 10 | import React from 'react'; 11 | import {shallow} from 'enzyme'; 12 | import renderer from 'react-test-renderer'; 13 | 14 | import PressMenu from '../index'; 15 | 16 | let tree = shallow(); 17 | 18 | it('PressMenu renders correctly', () => { 19 | let instance = tree.instance(); 20 | expect(instance.longPressTimeout).toEqual(null); 21 | }); 22 | -------------------------------------------------------------------------------- /components/PressMenu/example/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by TinySymphony on 2017-04-10. 3 | */ 4 | 5 | import React, {Component} from 'react'; 6 | import { 7 | ScrollView, 8 | Text, 9 | View, 10 | StyleSheet 11 | } from 'react-native'; 12 | 13 | import PressMenu from '../index'; 14 | 15 | export default class PressMenuExample extends Component { 16 | render() { 17 | return ( 18 | 19 | 20 | sdfssdf 21 | 22 | 23 | ); 24 | } 25 | } 26 | 27 | const styles = StyleSheet.create({ 28 | container: { 29 | width: 120, 30 | height: 60 31 | }, 32 | example: { 33 | flex: 1, 34 | justifyContent: 'center', 35 | alignItems: 'center' 36 | } 37 | }); 38 | -------------------------------------------------------------------------------- /components/PressMenu/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by TinySymphony on 2017-04-10. 3 | */ 4 | 5 | import React, {PropTypes, Component} from 'react'; 6 | import { 7 | View, 8 | Modal, 9 | StyleSheet, 10 | PanResponder 11 | } from 'react-native'; 12 | 13 | class PressMenu extends Component { 14 | static defaultProps = { 15 | startCapture: true, 16 | moveCapture: true 17 | } 18 | static propTypes = { 19 | startCapture: PropTypes.bool, 20 | moveCapture: PropTypes.bool 21 | } 22 | constructor(props) { 23 | super(props); 24 | this.state = { 25 | isModalVisible: false 26 | }; 27 | this.longPressTimeout = null; 28 | this.openModal = this.openModal.bind(this); 29 | this.closeModal = this.closeModal.bind(this); 30 | } 31 | componentWillMount () { 32 | this._panResponder = PanResponder.create({ 33 | onStartShouldSetPanResponder: this._handleStartShouldSetPanResponder.bind(this), 34 | onMoveShouldSetPanResponder: this._handleMoveShouldSetPanResponder.bind(this), 35 | onPanResponderGrant: this._handlePanResponderGrant.bind(this), 36 | onPanResponderMove: this._handlePanResponderMove.bind(this), 37 | onPanResponderRelease: this._handlePanResponderEnd.bind(this), 38 | onPanResponderTerminate: this._handlePanResponderEnd.bind(this), 39 | onStartShouldSetPanResponderCapture: () => false, 40 | onMoveShouldSetPanResponderCapture: (evt, gestureState) => true 41 | }); 42 | this._pan = PanResponder.create({ 43 | onStartShouldSetPanResponder: this._handleStartShouldSetPanResponder.bind(this), 44 | onMoveShouldSetPanResponder: this._handleMoveShouldSetPanResponder.bind(this), 45 | onPanResponderGrant: this._handlePanResponderGrant.bind(this), 46 | onPanResponderMove: this._handlePanResponderMove.bind(this), 47 | onPanResponderRelease: this._handlePanResponderEnd.bind(this), 48 | onPanResponderTerminate: this._handlePanResponderEnd.bind(this), 49 | onStartShouldSetPanResponderCapture: () => true, 50 | onMoveShouldSetPanResponderCapture: (evt, gestureState) => true 51 | }); 52 | } 53 | _handleStartShouldSetPanResponder (e: Object, gestureState: Object) { 54 | // Should we become active when the user presses down on the circle? 55 | clearTimeout(this.longPressTimeout); 56 | this.longPressTimeout = setTimeout(() => { 57 | this.setState({ 58 | isModalVisible: true 59 | }); 60 | }, 1000); 61 | return true; 62 | } 63 | _handleMoveShouldSetPanResponder (e: Object, gestureState: Object) { 64 | return false; 65 | } 66 | _handlePanResponderGrant (e: Object, gestureState: Object) { 67 | } 68 | _handlePanResponderMove (e: Object, gestureState: Object) { 69 | } 70 | _handlePanResponderEnd (e: Object, gestureState: Object) { 71 | console.log('end', e.target); 72 | clearTimeout(this.longPressTimeout); 73 | } 74 | openModal () { 75 | this.setState({ 76 | isModalVisible: true 77 | }); 78 | } 79 | closeModal () { 80 | this.setState({ 81 | isModalVisible: false 82 | }); 83 | } 84 | render() { 85 | return ( 86 | 89 | {this.props.children} 90 | 94 | 95 | {this.props.children} 96 | 97 | 98 | 99 | ); 100 | } 101 | } 102 | 103 | class MenuItem extends Component { 104 | constructor(props) { 105 | super(props); 106 | } 107 | } 108 | 109 | PressMenu.MeunItem = MenuItem; 110 | export default PressMenu; 111 | 112 | const styles = StyleSheet.create({ 113 | container: { 114 | }, 115 | mask: { 116 | flex: 1, 117 | backgroundColor: 'rgba(255, 255, 255, 0.86)' 118 | } 119 | }); 120 | -------------------------------------------------------------------------------- /components/PressMenu/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-press-menu", 3 | "version": "0.0.1", 4 | "description": "a component reacts to user's long press action and offers a customizable menu. (like pinterest)", 5 | "main": "./index.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/xgfe/react-native-ui-xg.git" 9 | }, 10 | "keywords": [ 11 | "react-native", 12 | "xgfe" 13 | ], 14 | "author": "xgfe", 15 | "license": "MIT", 16 | "bugs": { 17 | "url": "https://github.com/xgfe/react-native-ui-xg/issues" 18 | }, 19 | "homepage": "https://github.com/xgfe/react-native-ui-xg#readme" 20 | } 21 | -------------------------------------------------------------------------------- /components/Tab/.npmignore: -------------------------------------------------------------------------------- 1 | example/ 2 | __tests__/ 3 | .* 4 | components/ 5 | coverage/ 6 | index.android.js 7 | index.ios.js 8 | android/ 9 | ios/ 10 | -------------------------------------------------------------------------------- /components/Tab/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 鲜果FE 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, 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, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /components/Tab/README.md: -------------------------------------------------------------------------------- 1 | ### The react-native-tab-xg 2 | * react native Tab component for both Android and iOS based on pure JavaScript 3 | 4 | ### Main 5 | * This component provide a Tab function for you with which you can handle your own routers 6 | 7 | ### Properties 8 | link 9 | ![image](https://raw.githubusercontent.com/lulutia/images/master/react-native-components/Screen-Capture-43.gif) 10 | 11 | ### Properties 12 | 13 | | Prop | Default | Type | Description | 14 | | :------------ |:---------------:| :---------------:| :-----| 15 | | itemList | - | `Array` | Specify the content of the tab | 16 | | active | - | `string` | Specify the actived tab | 17 | 18 | ###inSide itemList We Provide some keys for you to custome the content 19 | | key | Default | Type | Description | 20 | | :------------ |:---------------:| :---------------:| :-----| 21 | | key | - | `string` | to compare with the active key | 22 | | title | - | `string` | the text of the tab | 23 | | icon | - | `node` | the icon of your tab(for more info you can see the example) | 24 | -------------------------------------------------------------------------------- /components/Tab/Tab.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import { 3 | View, 4 | Text, 5 | TouchableWithoutFeedback 6 | } from 'react-native'; 7 | import Style from './TabStyle'; 8 | 9 | 10 | class Tab extends Component { 11 | 12 | // 构造 13 | constructor(props) { 14 | super(props); 15 | this.renderMenuItems = this.renderMenuItems.bind(this); 16 | } 17 | 18 | 19 | renderMenuItems() { 20 | const { 21 | active, 22 | itemList 23 | } = this.props; 24 | return itemList && itemList.map((item) => { 25 | const color = active === item.key ? '#ff9900' : '#999'; 26 | 27 | return ( 28 | active !== item.key && item.onPress()} 30 | > 31 | 32 | {item.icon} 33 | {item.title} 37 | 38 | 39 | ); 40 | }); 41 | } 42 | 43 | render() { 44 | 45 | return ( 46 | 47 | {this.renderMenuItems()} 48 | 49 | ); 50 | } 51 | } 52 | 53 | export default Tab; 54 | -------------------------------------------------------------------------------- /components/Tab/TabStyle.js: -------------------------------------------------------------------------------- 1 | import StyleSheet from 'react-native-stylesheet-xg'; 2 | 3 | export const IMG = { 4 | homeIcon: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAI/0lEQVR4Xu3dsY4cRRDG8VpkCVlEvAcIiRQLkUGI5NgBstcrBw54E9LbQZZDywkEBA4sWXLglIiHcWANWrEHx/lud6a7qru66k9Kd3X3V/XTHea8txH+IQESuDWBDdmQAAncngBAmA4SOJEAQBgPEgAIM0ACZQnwFaQsN3YlSQAgSRrNM8sSAEhZbuxKkgBAkjSaZ5YlAJCy3NiVJAGAJGk0zyxLID2Q3W737cXFxduy+NgVPYHUQHa73U/zPP86z/PzaZoeicgcveG8b10CaYFc4hCRTw6RzfP8DCTrhifD6pRAruO4bDRIMoz8ujemA7Ldbu9vNpuXl185rscFknUDFH11KiBHHC9E5M6pxoIk+tgvf18aIEtx8O3W8uHJsDIFkLU4QJJh9Je9MTyQUhwgWTZA0VeFBlKLAyTRx//8+8IC0cIBkvNDFHlFSCDaOEASmcDpt4UDYoUDJDmRhAJijQMk+ZCEAdIKB0hyIQkBpDUOkORBMjyQXjhAkgPJ0EB64wBJfCSjA3mz2Wy+89Cm4w84PvRwF+6gl8DQQB48ePDZ3bt3X4nIPb1IyivxU8Dl2XndOTSQQ6gg8TpaMe41PBCQxBhEr68IAQQkXsdr/HuFAQKS8YfR4wtCAQGJxxEb+07hgIBk7IH0dvuQQEDibczGvU9YICAZdyg93Tw0EJB4GrUx7xIeCEjGHEwvt04BBCRexm28e6QBApLxhtPDjVMBAYmHkRvrDumAgGSsAe1925RAQNJ77MY5Py0QkIwzpD1vmhoISHqO3hhnpwcCkjEGtdctAXJMnr+Z2GsEfZ8LkCv9AYnvYe1xO4BcS90pEj4tpYcOEQHIDcF7QyIiv+z3+587zUjqYwFyS/tBktrFv48HyIk5AAlIAHJmBkCSGwlAFvQfJAtCCroEIAsbC5KFQQVbBpAVDQXJirCCLAXIykaCZGVggy8HSEEDQVIQ2qBbAFLYOJAUBjfYNoBUNAwkFeENshUglY0CSWWAzrcDRKFBIFEI0WkJgCg1BiRKQTorAxDFhoBEMUwnpQCi3AiQKAfauRxADBoAEoNQO5UEiFHwIDEKtnFZgBgGDhLDcBuVBohx0CAxDti4PECMAz6UB0mDkI2OAIhRsNfLgqRR0MrHAEQ50FPlQNIwbKWjAKIU5NIyIFmalI91AOnQB5B0CL3wSIAUBle7DSS1CbbZD5A2Od94yhHJWxH5uuM1rh7NJzheawRAOk/mkydPPv/w4cNrkHRuxC3HA8RBX0DioAkA8duEw81A4rM/fAVx1BdvSOZ5fjdN0zeOImp+FYA0j/z0gQ6R/DVN05ciMjuLqsl1ANIk5nWHgGRdXparAWKZbkVtkFSEp7gVIIphapdyiuQL7Xd6rgcQz93x+adbf+73ey//Y9O8ewAxj7j+AG9fSUQkDRKA1M9vkwogaRLzR4cApE/uRaeCpCi2qk0AqYqv/WaQtM0cIG3zVjkNJCoxLioCkEUx+VsEkjY9AUibnE1OAYlJrP8rChD7jE1PAIlpvAIQ23ybVAeJXcwAscu2aWWQ2MQNEJtcu1QFiX7sANHPtGvFI5I3IvJV14v8d/jQP5YCECdTpHUNgGgl+U8dgOjm2bUa32Lpxw8Q/Uy7VASHTewAscm1aVVw2MUNELtsm1QGh23MALHN17Q6OEzj5T/S7eO1OwEcdtlercxXkDY5q54CDtU4TxYDSLusVU4Ch0qMi4sAZHFU/ReCo30PANI+86ITwVEUW/UmgFRHaF8AHPYZ33YCQPplv+hkcCyKyWwRQMyirS/sDcc8z4dPeuejR+tbS4XaBJziSPdrEPgKUjvJBvvBYRBqYUmAFAZntQ0cVsmW1QVIWW4muxz+Wuh3+/2eX8Fm0m2KrkrgiOOViNxbtdFuMb8znb9RaDddayqDY01abdfyLVbbvD86DRydG3DmeIB07A84Ooa/8GiALAxKexk4tBO1qQcQm1xPVgVHh9ALjwRIYXCl28BRmlyffQBpmDs4GoatdBRAlII8VwYc5xLy+e8B0qAv4GgQstERADEK9rIsOIwDNi4PEMOAwWEYbqPSADEKGhxGwTYuCxCDwMFhEGqnkgBRDh4cyoF2LgcQxQaAQzFMJ6UAotQIcCgF6awMQBQaAg6FEJ2WAEhlY8BRGaDz7QCpaBA4KsIbZCtAChsFjsLgBtsGkIKGgaMgtEG3AGRl48CxMrDBlwNkRQPBsSKsIEsBsrCR3nDM8/xsmqaHC6/PssIEALIgOKc4HonIvOD6LKlIACBnwgNHxXQF2AqQE00ER4AJr3wCQG4JEByVkxVkO0BuaCQ4gky3wjMAci1EcChMVaASALnSTHAEmmylpwDkGCQ4lCYqWBmAiAg4gk214nPSAwGH4jQFLJUaCDgCTrTyk9ICAYfyJAUtlxIIOIJOs8Gz0gEBh8EUBS6ZCgg4Ak+y0dPSAAGH0QQFL5sCCDiCT7Hh88IDAYfh9CQoHRoIOBJMsPETwwIBh/HkJCkfEgg4kkxvg2eGAwKOBlOT6IhQQMCRaHIbPTUMEHA0mphkx4QA8vTp00/fv3//WkTueejf8UPd+NwqD82ovMPwQI44fheRHyqzUNkODpUY3RQZGgg43MxR2IsMDeTx48e/iciPHrrDZ+V66IL+HYYGst1uv99sNn+IyB39aJZX5Nuq5VmNtnJoIIewt9vt/c1m86IXEnCMNvLr7js8kJ5IwLFu2EZcHQJIDyTgGHHc1985DJCWSMCxftBG3REKSAsk4Bh11MvuHQ6IJRJwlA3ZyLtCArFAAo6Rx7z87mGBaCIBR/mAjb4zNBANJOAYfcTr7h8eSA0ScNQNV4TdKYCUIAFHhPGuf0MaIGuQgKN+sKJUSAVkCRJwRBltnXekA3IKCTh0hipSlZRAbkICjkhjrfeWtECuIHk5z/PzaZr4O+R6cxWmUmoghy7udrtvLy4u3obpKA9RTSA9ENU0KRYuAYCEaykP0kwAIJppUitcAgAJ11IepJkAQDTTpFa4BAASrqU8SDMBgGimSa1wCQAkXEt5kGYCANFMk1rhEgBIuJbyIM0EAKKZJrXCJfA3PpxyFPtlhb8AAAAASUVORK5CYII=' 5 | }; 6 | 7 | const Style = StyleSheet.create({ 8 | menu: { 9 | position: 'absolute', 10 | bottom: 0, 11 | height: 44, 12 | left: 0, 13 | right: 0, 14 | flexDirection: 'row', 15 | backgroundColor: '#ffffff', 16 | borderTopWidth: 1, 17 | borderTopColor: '#d8d8d8' 18 | }, 19 | menuItem: { 20 | flex: 1, 21 | alignItems: 'center', 22 | justifyContent: 'center' 23 | }, 24 | menuTitle: { 25 | fontSize: 12 26 | } 27 | }); 28 | 29 | export default Style; 30 | -------------------------------------------------------------------------------- /components/Tab/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-tab-xg", 3 | "version": "0.0.1", 4 | "description": "react native tab component for both Android and IOS, useing pure JavaScript", 5 | "main": "Tab.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/xgfe/react-native-ui-xg.git" 9 | }, 10 | "keywords": [ 11 | "react-native", 12 | "tabs", 13 | "tab", 14 | "react-native-tab" 15 | ], 16 | "author": "xgfe", 17 | "license": "MIT", 18 | "bugs": { 19 | "url": "https://github.com/xgfe/react-native-ui-xg/issues" 20 | }, 21 | "homepage": "https://github.com/xgfe/react-native-ui-xg/components/Tab#readme", 22 | "dependencies": { 23 | "react-native-stylesheet-xg": "^1.1.0" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /components/ZoomImage/.npmignore: -------------------------------------------------------------------------------- 1 | example 2 | __tests__ 3 | .* 4 | -------------------------------------------------------------------------------- /components/ZoomImage/Animation.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by TinySymphony on 2017-02-14. 3 | */ 4 | 5 | export default function Animation(option) { 6 | this.animate = this.animate.bind(this); 7 | this.start = this.start.bind(this); 8 | this.option = option; 9 | } 10 | 11 | Animation.prototype.animate = function (now) { 12 | const { 13 | start, 14 | end, 15 | duration, 16 | onAnimationFrame, 17 | onAnimationEnd, 18 | easingFunc = this.defaultEasing 19 | } = this.option; 20 | 21 | let currentDuration = now - this.startTime; 22 | if (currentDuration >= duration) { 23 | onAnimationFrame(end); 24 | onAnimationEnd(); 25 | return; 26 | } 27 | let value; 28 | if (start > end) { 29 | value = start - (start - end) * easingFunc(currentDuration / duration); 30 | } else { 31 | value = (end - start) * easingFunc(currentDuration / duration) + start; 32 | } 33 | onAnimationFrame(value); 34 | requestAnimationFrame(this.animate); 35 | }; 36 | 37 | Animation.prototype.start = function (time) { 38 | this.startTime = new Date(); 39 | this.animate(time || this.startTime); 40 | }; 41 | 42 | Animation.prototype.defaultEasing = t => t; 43 | -------------------------------------------------------------------------------- /components/ZoomImage/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 鲜果FE 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, 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, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /components/ZoomImage/README.md: -------------------------------------------------------------------------------- 1 | ## react-native-zoom-image 2 | 3 | ZoomImage component for React Native Application (ios / android) 4 | 5 | > **Only works with https network images** [With the limitation of the current react-native, we can't get original size of required images. This component just zooms them with given size (provided by `imgStyle` prop)] 6 | 7 | > If you need to support http network images, modify info.plist please :) 8 | 9 | ### Examples 10 | 11 | See at [this page](https://github.com/Tinysymphony/react-native-zoom-image#readme) 12 | 13 | ### Usage 14 | 15 | **install from npm** 16 | 17 | ``` shell 18 | npm install --save react-native-zoom-image 19 | 20 | ``` 21 | 22 | **import in project** 23 | 24 | ``` js 25 | import ZoomImage from 'react-native-zoom-image'; 26 | import {Easing} from 'react-native'; // import Easing if you want to customize easing function 27 | ``` 28 | 29 | ```js 30 | let styles = { 31 | img: {} // custom styles of original image component 32 | }; 33 | // in render function 34 | 42 | 43 | ``` 44 | 45 | ## Properties 46 | 47 | | Prop | Type | Default | Description | 48 | | --- | --- | --- | --- | 49 | | disabled | bool | false | Whether to disable the component or not. | 50 | | startCapture | bool | false | Whether to capture start touch event or not. | 51 | | moveCapture | bool | false | Whether to capture move event or not. | 52 | | responderNegotiate | function | - | Use custom conditions to enable or disable gesture over image modal. | 53 | | easingFunc | function | Easing.linear | The easing function of animation. | 54 | | showDuration | number | 100 | The duration of showing the image modal. | 55 | | closeDuration | number | 140 | The duration of closing the image modal. | 56 | | rebounceDuration | number | 800 | The total duration of resetting the position of image. The actual duration changes by the displacement of the image in Y-axis. If the displacement equals to the height of screen, the duration shall be 800ms. | 57 | | enableScaling | bool | false | Whether to scale the image when it is polled. | 58 | 59 | ### Instance methods 60 | 61 | | Method | Params | Description | 62 | | --- | --- | --- | 63 | | openModal | - | Open image modal | 64 | | closeModal | - | Close image modal. | 65 | 66 | LICENSE MIT 67 | -------------------------------------------------------------------------------- /components/ZoomImage/__tests__/test.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | import { 4 | View, 5 | Text, 6 | Easing, 7 | Dimensions, 8 | StyleSheet 9 | } from 'react-native'; 10 | import React from 'react'; 11 | import {shallow} from 'enzyme'; 12 | import renderer from 'react-test-renderer'; 13 | 14 | import ZoomImage from '../index'; 15 | import Animation from '../Animation'; 16 | 17 | let {width, height, scale} = Dimensions.get('window'); 18 | 19 | const styles = StyleSheet.create({ 20 | img: { 21 | borderWidth: 3, 22 | borderColor: '#45b7d5' 23 | } 24 | }); 25 | 26 | let duration = 100; 27 | let treeA = shallow( 28 | 34 | ); 35 | 36 | test('ZoomImage', (done) => { 37 | let instance = treeA.instance(); 38 | instance.componentDidMount(); 39 | expect(instance.enableModal).toEqual(false); 40 | expect(instance.getMaxSizeByRatio(1.4).width).toEqual(750); 41 | expect(instance.getMaxSizeByRatio(0.4).height).toEqual(1334); 42 | instance.openModal(); 43 | instance.modalRefBind('modal'); 44 | expect(instance._modal).toEqual('modal'); 45 | done(); 46 | }); 47 | 48 | test('Animation works', (done) => { 49 | var animate = new Animation({ 50 | start: 200, 51 | end: 10, 52 | onAnimationFrame: () => { 53 | expect(Animation.prototype.defaultEasing(3)).toEqual(3); 54 | }, 55 | onAnimationEnd: done, 56 | duration: 200 57 | }).start(12313100000000); 58 | }); 59 | -------------------------------------------------------------------------------- /components/ZoomImage/example/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by TinySymphony on 2017-03-23. 3 | */ 4 | 5 | import React, {Component} from 'react'; 6 | import { 7 | StyleSheet, 8 | View, 9 | Text, 10 | Easing, 11 | ScrollView 12 | } from 'react-native'; 13 | 14 | import ZoomImage from '../index'; 15 | 16 | export default class ZoomImageExample extends Component { 17 | constructor(props) { 18 | super(props); 19 | this.text = ''; 20 | } 21 | render() { 22 | return ( 23 | 24 | 25 | Zoom Image Examples! Try to click them~ 26 | 27 | 28 | 33 | 34 | 35 | 36 | 42 | 43 | 44 | 45 | 51 | 52 | 53 | 54 | 55 | ); 56 | } 57 | } 58 | 59 | const styles = StyleSheet.create({ 60 | content: { 61 | justifyContent: 'center', 62 | alignItems: 'center' 63 | }, 64 | txt: { 65 | fontSize: 16, 66 | marginTop: 20, 67 | color: '#333' 68 | }, 69 | img: { 70 | borderWidth: 3, 71 | borderColor: '#45b7d5' 72 | }, 73 | imgItem: { 74 | justifyContent: 'center', 75 | alignItems: 'center', 76 | margin: 20 77 | } 78 | }); 79 | -------------------------------------------------------------------------------- /components/ZoomImage/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-zoom-image", 3 | "version": "0.1.1", 4 | "description": "", 5 | "main": "./index.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/xgfe/react-native-ui-xg.git" 9 | }, 10 | "keywords": [ 11 | "react-native", 12 | "xgfe" 13 | ], 14 | "author": "xgfe", 15 | "license": "MIT", 16 | "bugs": { 17 | "url": "https://github.com/xgfe/react-native-ui-xg/issues" 18 | }, 19 | "homepage": "https://github.com/xgfe/react-native-ui-xg#readme" 20 | } 21 | -------------------------------------------------------------------------------- /components/package.json: -------------------------------------------------------------------------------- 1 | {"name": "components"} 2 | -------------------------------------------------------------------------------- /example/Home.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import { 3 | Text, 4 | View, 5 | ScrollView, 6 | TouchableHighlight, 7 | Image 8 | } from 'react-native'; 9 | import {Navigation} from 'react-native-navigation'; 10 | 11 | import styles from './HomeStyle'; 12 | import {scenes} from './registerScreens'; 13 | 14 | export default class Home extends Component { 15 | // 构造 16 | constructor(props) { 17 | super(props); 18 | // 初始状态 19 | this.navigation = this.navigation.bind(this); 20 | } 21 | 22 | navigation(key) { 23 | this.props.navigator.push({ 24 | screen: key, 25 | title: key, 26 | animationType: 'slide-horizontal' 27 | }); 28 | } 29 | 30 | render() { 31 | let listStr = []; 32 | for (let key in scenes) { 33 | if (key === 'Home') { 34 | continue; 35 | } 36 | 37 | listStr.push( 38 | this.navigation(key)} key={key}> 39 | 40 | 41 | 42 | {key} 43 | 44 | 45 | 46 | 47 | ); 48 | } 49 | 50 | return ( 51 | 52 | React Native UI xg 53 | 54 | {listStr} 55 | 56 | 57 | ); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /example/HomeStyle.js: -------------------------------------------------------------------------------- 1 | import {StyleSheet} from 'react-native'; 2 | 3 | const styles = StyleSheet.create({ 4 | container: { 5 | flex: 1, 6 | backgroundColor: '#f1f1f1' 7 | }, 8 | title: { 9 | margin: 20, 10 | fontSize: 25, 11 | textAlign: 'center', 12 | color: '#666' 13 | }, 14 | listView: { 15 | marginBottom: 20, 16 | backgroundColor: '#fff', 17 | borderTopWidth: 1, 18 | borderTopColor: '#ddd', 19 | borderBottomWidth: 1, 20 | borderBottomColor: '#ddd' 21 | }, 22 | listItem: { 23 | flexDirection: 'row', 24 | height: 46, 25 | alignItems: 'center' 26 | }, 27 | itemText: { 28 | flex: 1, 29 | fontSize: 16, 30 | color: '#333' 31 | }, 32 | right: { 33 | width: 18, 34 | height: 18, 35 | marginRight: 5 36 | }, 37 | itemBody: { 38 | flex: 1, 39 | height: 46, 40 | flexDirection: 'row', 41 | borderBottomWidth: 1, 42 | alignItems: 'center', 43 | borderBottomColor: '#ddd' 44 | }, 45 | logo: { 46 | width: 36, 47 | height: 36, 48 | marginLeft: 5, 49 | marginRight: 5 50 | } 51 | }); 52 | 53 | export default styles; 54 | -------------------------------------------------------------------------------- /example/registerScreens.js: -------------------------------------------------------------------------------- 1 | // !important: Don't modify this file manually. 2 | 3 | // #anchor# 4 | import CalendarSelect from '../components/CalendarSelect/example'; 5 | import Accordion from '../components/Accordion/example'; 6 | import ZoomImage from '../components/ZoomImage/example'; 7 | import ActionSheet from '../components/ActionSheet/example'; 8 | import DatePicker from '../components/DatePicker/example'; 9 | import Drawer from '../components/Drawer/example'; 10 | import LabelSelect from '../components/LabelSelect/example'; 11 | import Grading from '../components/Grading/example'; 12 | import Button from '../components/Button/example'; 13 | import Input from '../components/Input/example'; 14 | import Confirm from '../components/Confirm/example'; 15 | import Link from '../components/Link/example'; 16 | import Tab from '../components/Tab/example'; 17 | import Home from './Home'; 18 | 19 | const scenes = { 20 | // #list# 21 | CalendarSelect, 22 | Accordion, 23 | ZoomImage, 24 | ActionSheet, 25 | DatePicker, 26 | Drawer, 27 | Grading, 28 | LabelSelect, 29 | Button, 30 | Input, 31 | Confirm, 32 | Link, 33 | Tab, 34 | Home 35 | }; 36 | 37 | import {Navigation} from 'react-native-navigation'; 38 | 39 | export {scenes}; 40 | 41 | // register all screens of the app (including internal ones) 42 | export default function registerScreens() { 43 | for (let key in scenes) { 44 | Navigation.registerComponent(key, () => scenes[key]); 45 | } 46 | } 47 | 48 | -------------------------------------------------------------------------------- /example/res/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xgfe/react-native-ui-xg/59f111fdb0fcb416948212f941d2fc2f486d4adb/example/res/logo.png -------------------------------------------------------------------------------- /example/res/right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xgfe/react-native-ui-xg/59f111fdb0fcb416948212f941d2fc2f486d4adb/example/res/right.png -------------------------------------------------------------------------------- /index.android.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Sample React Native App 3 | * https://github.com/facebook/react-native 4 | * @flow 5 | */ 6 | 7 | require('./index.ios'); 8 | -------------------------------------------------------------------------------- /index.ios.js: -------------------------------------------------------------------------------- 1 | import {Navigation} from 'react-native-navigation'; 2 | 3 | import registerScreens from './example/registerScreens'; 4 | 5 | registerScreens(); // this is where you register all of your app's screens 6 | 7 | // start the app 8 | Navigation.startSingleScreenApp({ 9 | screen: { 10 | screen: 'Home', // unique ID registered with Navigation.registerScreen 11 | title: 'Welcome', // title of the screen as appears in the nav bar (optional) 12 | navigatorStyle: { 13 | navBarBackgroundColor: '#f7f7f8' 14 | }, // override the navigator style for the screen, see "Styling the navigator" below (optional) 15 | navigatorButtons: {} // override the nav buttons for the screen, see "Adding buttons to the navigator" below (optional) 16 | }, 17 | animationType: 'none' 18 | }); 19 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | export {default as DatePicker} from 'react-native-datepicker'; 2 | export {default as Button} from 'react-native-buttons'; 3 | export {default as DrawerMenu} from 'react-native-drawer-menu'; 4 | export {default as Grading} from 'react-native-grading'; 5 | export {default as LabelSelect} from 'react-native-label-select'; 6 | export {default as ZoomImage} from 'react-native-zoom-image'; 7 | export {default as Input} from 'react-native-input-xg'; 8 | export {default as Confirm} from 'react-native-confirm'; 9 | export {default as Link} from 'react-native-link-xg'; 10 | export {default as Tab} from 'react-native-tab-xg'; 11 | export {default as StyleSheet} from 'react-native-stylesheet-xg'; 12 | export {default as Accordion} from 'react-native-accordion-xg'; 13 | export {default as CalendarSelect} from 'react-native-calendar-select'; 14 | -------------------------------------------------------------------------------- /ios/reactNativeUiXg-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 | -------------------------------------------------------------------------------- /ios/reactNativeUiXg-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 | -------------------------------------------------------------------------------- /ios/reactNativeUiXg/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 | -------------------------------------------------------------------------------- /ios/reactNativeUiXg/AppDelegate.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 "AppDelegate.h" 11 | 12 | #import 13 | #import 14 | #import "RCCManager.h" 15 | 16 | @implementation AppDelegate 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 19 | { 20 | NSURL *jsCodeLocation; 21 | 22 | jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil]; 23 | 24 | /* 25 | RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation 26 | moduleName:@"reactNativeUiXg" 27 | initialProperties:nil 28 | launchOptions:launchOptions]; 29 | rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1]; 30 | 31 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 32 | UIViewController *rootViewController = [UIViewController new]; 33 | rootViewController.view = rootView; 34 | self.window.rootViewController = rootViewController; 35 | [self.window makeKeyAndVisible]; 36 | */ 37 | 38 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 39 | self.window.backgroundColor = [UIColor whiteColor]; 40 | [[RCCManager sharedInstance] initBridgeWithBundleURL:jsCodeLocation launchOptions:launchOptions]; 41 | 42 | return YES; 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /ios/reactNativeUiXg/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 | -------------------------------------------------------------------------------- /ios/reactNativeUiXg/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 | } -------------------------------------------------------------------------------- /ios/reactNativeUiXg/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | reactNativeUiXg 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 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UIViewControllerBasedStatusBarAppearance 40 | 41 | NSLocationWhenInUseUsageDescription 42 | 43 | NSAppTransportSecurity 44 | 45 | 46 | NSExceptionDomains 47 | 48 | localhost 49 | 50 | NSExceptionAllowsInsecureHTTPLoads 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /ios/reactNativeUiXg/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 | -------------------------------------------------------------------------------- /ios/reactNativeUiXgTests/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 | -------------------------------------------------------------------------------- /ios/reactNativeUiXgTests/reactNativeUiXgTests.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 reactNativeUiXgTests : XCTestCase 20 | 21 | @end 22 | 23 | @implementation reactNativeUiXgTests 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 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-ui-xg", 3 | "version": "0.0.6", 4 | "description": "A suit of react native ui.", 5 | "main": "index.js", 6 | "private": false, 7 | "scripts": { 8 | "start": "node node_modules/react-native/local-cli/cli.js start", 9 | "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s", 10 | "lint": "eslint . --fix", 11 | "test": "jest --coverage", 12 | "coverage": "cat ./coverage/lcov.info | coveralls", 13 | "check": "node ./tools/checkGit", 14 | "new": "node ./tools/new", 15 | "ios": "react-native run-ios", 16 | "android": "react-native run-android" 17 | }, 18 | "dependencies": { 19 | "react-native-datepicker": "^1.5.0", 20 | "react-native-drawer-menu": "^0.2.3", 21 | "react-native-grading": "^1.0.3", 22 | "react-native-label-select": "^1.0.10", 23 | "react-native-zoom-image": "^0.1.1", 24 | "react-native-buttons": "^0.0.4", 25 | "react-native-stylesheet-xg": "^1.1.0", 26 | "react-native-input-xg": "^0.0.2", 27 | "react-native-confirm": "^0.0.1", 28 | "react-native-link-xg": "^0.0.1", 29 | "react-native-tab-xg": "^0.0.1", 30 | "react-native-accordion-xg": "^0.0.1", 31 | "react-native-action-sheet-xg": "^0.0.1", 32 | "react-native-calendar-select": "^0.1.0" 33 | }, 34 | "devDependencies": { 35 | "babel-jest": "20.0.3", 36 | "babel-preset-react-native": "2.1.0", 37 | "coveralls": "^2.11.16", 38 | "cz-conventional-changelog": "^1.2.0", 39 | "enzyme": "^2.9.1", 40 | "inquirer": "^3.0.5", 41 | "jest": "20.0.4", 42 | "jsdom": "^9.11.0", 43 | "pre-commit": "^1.2.2", 44 | "react": "16.0.0-alpha.12", 45 | "react-native": "0.46.2", 46 | "react-native-navigation": "^1.1.134", 47 | "react-test-renderer": "16.0.0-alpha.12" 48 | }, 49 | "config": { 50 | "commitizen": { 51 | "path": "./node_modules/cz-conventional-changelog" 52 | } 53 | }, 54 | "jest": { 55 | "preset": "react-native", 56 | "testPathIgnorePatterns": [ 57 | "/node_modules/", 58 | "tools/" 59 | ] 60 | }, 61 | "pre-commit": [ 62 | "check", 63 | "lint" 64 | ] 65 | } 66 | -------------------------------------------------------------------------------- /tools/checkGit.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | const cp = require('child_process'); 3 | const fs = require('fs'); 4 | 5 | // start 6 | cp.exec('git config user.email', function (err, stdout, stderr) { 7 | if(err || stderr) { 8 | console.log('\x1b[31m%s\x1b[1m', '获取git账号名失败'); 9 | process.exit(1); 10 | } 11 | var email = stdout.trim(); 12 | if(!email || email.split('@')[1] === 'meituan.com') { 13 | console.log('\x1b[31m%s\x1b[1m', '请勿使用公司邮箱提交'); 14 | process.exit(1); 15 | } 16 | }); 17 | -------------------------------------------------------------------------------- /tools/component/.npmignore: -------------------------------------------------------------------------------- 1 | example 2 | __tests__ 3 | .* 4 | -------------------------------------------------------------------------------- /tools/component/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 鲜果FE 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, 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, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /tools/component/README.md: -------------------------------------------------------------------------------- 1 | ## react-native#(name)# 2 | 3 | #(NAME)# component for React Native Application (ios / android) 4 | 5 | 6 | ### Examples 7 | 8 | 9 | ### Usage 10 | 11 | **install from npm** 12 | 13 | ``` shell 14 | npm install --save react-native#(name)# 15 | ``` 16 | 17 | **import in project** 18 | 19 | ``` js 20 | import #(NAME)# from 'react-native#(name)#'; 21 | ``` 22 | 23 | ## Properties 24 | 25 | ### Instance methods 26 | 27 | LICENSE MIT 28 | -------------------------------------------------------------------------------- /tools/component/__tests__/test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by #(AUTHOR)# on #(DATE)#. 3 | */ 4 | 5 | /* eslint-disable */ 6 | 7 | import { 8 | View 9 | } from 'react-native'; 10 | import React from 'react'; 11 | import {shallow} from 'enzyme'; 12 | import renderer from 'react-test-renderer'; 13 | 14 | import #(NAME)# from '../index'; 15 | 16 | it('#(NAME)# renders correctly', () => { 17 | }); 18 | -------------------------------------------------------------------------------- /tools/component/example/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by #(AUTHOR)# on #(DATE)#. 3 | */ 4 | 5 | import React, {Component} from 'react'; 6 | import { 7 | StyleSheet, 8 | View 9 | } from 'react-native'; 10 | 11 | import #(NAME)# from '../index'; 12 | 13 | export default class #(NAME)#Example extends Component { 14 | render() { 15 | return ( 16 | <#(NAME)# style={styles.example}> 17 | ); 18 | } 19 | } 20 | 21 | const styles = StyleSheet.create({ 22 | example: { 23 | flex: 1, 24 | justifyContent: 'center', 25 | alignItems: 'center' 26 | } 27 | }); 28 | -------------------------------------------------------------------------------- /tools/component/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by #(AUTHOR)# on #(DATE)#. 3 | */ 4 | 5 | import React, {PropTypes, Component} from 'react'; 6 | import { 7 | StyleSheet, 8 | View 9 | } from 'react-native'; 10 | 11 | export default class #(NAME)# extends Component { 12 | static defaultProps = { 13 | } 14 | static propTypes = { 15 | } 16 | constructor(props) { 17 | super(props); 18 | } 19 | componentWillMount() { 20 | } 21 | componentDidMount() { 22 | } 23 | render() { 24 | return 25 | } 26 | } 27 | 28 | const styles = StyleSheet.create({ 29 | container: { 30 | flex: 1 31 | } 32 | }); 33 | -------------------------------------------------------------------------------- /tools/component/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native#(name)#", 3 | "version": "0.0.1", 4 | "description": "#(DESC)#", 5 | "main": "./index.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/xgfe/react-native-ui-xg.git" 9 | }, 10 | "keywords": [ 11 | "react-native", 12 | "xgfe" 13 | ], 14 | "author": "xgfe", 15 | "license": "MIT", 16 | "bugs": { 17 | "url": "https://github.com/xgfe/react-native-ui-xg/issues" 18 | }, 19 | "homepage": "https://github.com/xgfe/react-native-ui-xg#readme" 20 | } 21 | -------------------------------------------------------------------------------- /tools/new.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | const cp = require('child_process'); 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | const inquirer = require('inquirer'); 6 | 7 | var name = ''; 8 | var author = ''; 9 | var target = ''; 10 | var date = (new Date()).toISOString().split('T').shift(); 11 | var desc = 'React Native Component'; 12 | var targetDir = path.resolve(__dirname, '../components'); 13 | var currentDir = path.resolve(__dirname, './component'); 14 | var isModule = false; 15 | 16 | // start 17 | cp.exec('git config user.name', function (err, stdout, stderr) { 18 | if(err || stderr) { 19 | console.log('获取git账号名失败'); 20 | process.exit(1); 21 | } 22 | author = stdout.trim(); 23 | inputNameAndDescription(); 24 | }); 25 | 26 | function inputNameAndDescription() { 27 | inquirer.prompt([{ 28 | type: 'input', 29 | name: 'name', 30 | message: 'Figure out a cname with CamelCase', 31 | validate: function(value) { 32 | if (!value) return 'Please Input A Name'; 33 | const modules = fs.readdirSync(targetDir).map(item => item.toLowerCase()) 34 | if (~modules.indexOf(value.toLowerCase())) return 'Duplicate Name'; 35 | return true; 36 | } 37 | }, { 38 | type: 'input', 39 | name: 'desc', 40 | message: 'Input description of this component' 41 | }]).then(function(answers) { 42 | name = answers.name; 43 | desc = answers.desc; 44 | target = targetDir + '/' + answers.name; 45 | cp.execSync(`cp -R ${currentDir} ${target}`); 46 | polishTarget(target); 47 | registerNew(); 48 | }); 49 | } 50 | 51 | function polishTarget(file) { 52 | var state = fs.lstatSync(file); 53 | if(state.isDirectory()) { 54 | const files = fs.readdirSync(file); 55 | files.forEach(item => { 56 | polishTarget(path.resolve(file, item)); 57 | }); 58 | } else { 59 | var str = fs.readFileSync(file, 'utf-8'); 60 | var res = str.replace(/#\(NAME\)#/g, name) 61 | .replace(/#\(name\)#/g, name.replace(/([A-Z])/g,"-$1").toLowerCase()) 62 | .replace(/#\(AUTHOR\)#/g, author) 63 | .replace(/#\(DATE\)#/g, date) 64 | .replace(/#\(DESC\)#/g, desc); 65 | fs.writeFileSync(file, res); 66 | } 67 | } 68 | 69 | function registerNew() { 70 | var exampleConfigFile = path.resolve(__dirname, '../example/config.js'); 71 | var content = fs.readFileSync(exampleConfigFile, 'utf-8'); 72 | var importString = `import ${name} from '../components/${name}/example';`; 73 | content = content.replace(/(\/\/\s*#anchor#)/, `$1\n${importString}`) 74 | .replace(/(\/\/\s*#list#)/, `$1\n ${name},`); 75 | fs.writeFile(exampleConfigFile, content, function () { 76 | console.log('\x1b[36m', `[Bravo] ${name} is Registered!` ,'\x1b[0m'); 77 | }); 78 | } 79 | --------------------------------------------------------------------------------