├── .clang-format ├── .eslintignore ├── .eslintrc.js ├── .flowconfig ├── .github ├── CODEOWNERS └── workflows │ ├── ci.yml │ └── publish.yml ├── .gitignore ├── .npmignore ├── .prettierrc ├── .releaserc ├── .yarn └── releases │ └── yarn-4.1.1.cjs ├── .yarnrc.yml ├── FabricExample ├── .bundle │ └── config ├── .eslintrc.js ├── .gitignore ├── .prettierrc.js ├── .watchmanconfig ├── App.tsx ├── Gemfile ├── Gemfile.lock ├── PickerExample.tsx ├── PickerIOSExample.tsx ├── PickerWindowsExamples.js ├── README.md ├── __tests__ │ └── App.test.tsx ├── android │ ├── app │ │ ├── build.gradle │ │ ├── debug.keystore │ │ ├── proguard-rules.pro │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── fabricexample │ │ │ │ ├── MainActivity.kt │ │ │ │ └── MainApplication.kt │ │ │ └── res │ │ │ ├── drawable │ │ │ └── rn_edit_text_material.xml │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ └── values │ │ │ ├── strings.xml │ │ │ └── styles.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle ├── app.json ├── babel.config.js ├── index.js ├── ios │ ├── .xcode.env │ ├── FabricExample.xcodeproj │ │ ├── project.pbxproj │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── FabricExample.xcscheme │ ├── FabricExample.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── FabricExample │ │ ├── AppDelegate.h │ │ ├── AppDelegate.mm │ │ ├── Images.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Info.plist │ │ ├── LaunchScreen.storyboard │ │ ├── PrivacyInfo.xcprivacy │ │ └── main.m │ ├── FabricExampleTests │ │ ├── FabricExampleTests.m │ │ └── Info.plist │ ├── Podfile │ └── Podfile.lock ├── jest.config.js ├── metro.config.js ├── package.json ├── tsconfig.json └── yarn.lock ├── LICENSE ├── README.md ├── RNCPicker.podspec ├── android ├── build.gradle ├── gradle.properties └── src │ ├── fabric │ └── java │ │ └── com │ │ └── reactnativecommunity │ │ └── picker │ │ └── FabricEnabledPicker.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── reactnativecommunity │ │ │ └── picker │ │ │ ├── CheckedTextViewImpl.java │ │ │ ├── PickerBlurEvent.java │ │ │ ├── PickerFocusEvent.java │ │ │ ├── PickerItemSelectEvent.java │ │ │ ├── RNCPickerPackage.java │ │ │ ├── ReactDialogPickerManager.java │ │ │ ├── ReactDropdownPickerManager.java │ │ │ ├── ReactPicker.java │ │ │ ├── ReactPickerLocalData.java │ │ │ ├── ReactPickerManager.java │ │ │ ├── ReactPickerShadowNode.java │ │ │ └── TextViewImpl.java │ ├── jni │ │ ├── CMakeLists.txt │ │ ├── RNCAndroidDialogPickerMeasurementsManager.cpp │ │ ├── RNCAndroidDialogPickerMeasurementsManager.h │ │ ├── RNCAndroidDialogPickerShadowNode.cpp │ │ ├── RNCAndroidDialogPickerShadowNode.h │ │ ├── RNCAndroidDialogPickerState.cpp │ │ ├── RNCAndroidDialogPickerState.h │ │ ├── RNCAndroidDropdownPickerMeasurementsManager.cpp │ │ ├── RNCAndroidDropdownPickerMeasurementsManager.h │ │ ├── RNCAndroidDropdownPickerShadowNode.cpp │ │ ├── RNCAndroidDropdownPickerShadowNode.h │ │ ├── RNCAndroidDropdownPickerState.cpp │ │ ├── RNCAndroidDropdownPickerState.h │ │ ├── conversions.h │ │ ├── react │ │ │ └── renderer │ │ │ │ └── components │ │ │ │ └── rnpicker │ │ │ │ ├── RNCAndroidDialogPickerComponentDescriptor.h │ │ │ │ └── RNCAndroidDropdownPickerComponentDescriptor.h │ │ ├── rnpicker.cpp │ │ └── rnpicker.h │ └── res │ │ ├── drawable │ │ ├── ic_dropdown.xml │ │ └── spinner_dropdown_background.xml │ │ └── layout │ │ ├── simple_spinner_dropdown_item.xml │ │ └── simple_spinner_item.xml │ └── paper │ └── java │ └── com │ ├── facebook │ └── react │ │ └── viewmanagers │ │ ├── RNCAndroidDialogPickerManagerDelegate.java │ │ ├── RNCAndroidDialogPickerManagerInterface.java │ │ ├── RNCAndroidDropdownPickerManagerDelegate.java │ │ └── RNCAndroidDropdownPickerManagerInterface.java │ └── reactnativecommunity │ └── picker │ └── FabricEnabledPicker.java ├── app.config.js ├── babel.config.js ├── e2e └── PickerAndroidTestModule.js ├── example ├── .gitignore ├── .watchmanconfig ├── android │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle ├── app.json ├── babel.config.js ├── index.js ├── ios │ └── Podfile ├── macos │ └── Podfile ├── metro.config.js ├── package.json ├── react-native.config.js ├── src │ ├── App.tsx │ ├── PickerExample.tsx │ ├── PickerIOSExample.tsx │ ├── PickerWindowsExamples.js │ └── __tests__ │ │ └── PickerExample.test.tsx ├── tsconfig.json └── windows │ └── .gitignore ├── index.js ├── ios ├── RNCPicker.h ├── RNCPicker.mm ├── RNCPicker.xcodeproj │ └── project.pbxproj ├── RNCPickerComponentView.h ├── RNCPickerComponentView.mm ├── RNCPickerFabricConversions.h ├── RNCPickerLabel.h ├── RNCPickerLabel.mm ├── RNCPickerManager.h └── RNCPickerManager.mm ├── jest.setup.js ├── js ├── AndroidDialogPickerNativeComponent.js ├── AndroidDropdownPickerNativeComponent.js ├── Picker.js ├── Picker.web.js ├── PickerAndroid.android.js ├── PickerAndroid.js ├── PickerAndroid.web.js ├── PickerIOS.ios.js ├── PickerIOS.js ├── PickerIOS.web.js ├── PickerItem.js ├── PickerMacOS.js ├── PickerMacOS.macos.js ├── PickerMacOS.web.js ├── PickerWindows.js ├── PickerWindows.web.js ├── PickerWindows.windows.js ├── RNCPickerNativeComponent.js ├── UnimplementedView.js ├── UnimplementedView.web.js ├── __tests__ │ ├── Picker.test.js │ └── __snapshots__ │ │ └── Picker.test.js.snap ├── index.js └── types.js ├── macos ├── RNCPicker.h ├── RNCPicker.m ├── RNCPicker.xcodeproj │ └── project.pbxproj ├── RNCPickerManager.h └── RNCPickerManager.m ├── metro.config.macos.js ├── package.json ├── react-native.config.js ├── screenshots ├── picker-android.png ├── picker-ios.png ├── picker-macos.png ├── picker-windows.png └── pickerios-ios.png ├── tsconfig.json ├── typings ├── Picker.d.ts ├── PickerIOS.d.ts └── index.d.ts ├── windows ├── .gitignore ├── NuGet.Config ├── ReactNativePicker.sln └── ReactNativePicker │ ├── PropertySheet.props │ ├── ReactNativePicker.def │ ├── ReactNativePicker.rc │ ├── ReactNativePicker.vcxproj │ ├── ReactPackageProvider.cpp │ ├── ReactPackageProvider.h │ ├── ReactPackageProvider.idl │ ├── ReactPickerView.cpp │ ├── ReactPickerView.h │ ├── ReactPickerView.idl │ ├── ReactPickerViewManager.cpp │ ├── ReactPickerViewManager.h │ ├── Reactnativepicker.vcxproj.filters │ ├── packages.config │ ├── pch.cpp │ ├── pch.h │ └── resource.h └── yarn.lock /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | AccessModifierOffset: -1 3 | AlignAfterOpenBracket: AlwaysBreak 4 | AlignConsecutiveAssignments: false 5 | AlignConsecutiveDeclarations: false 6 | AlignEscapedNewlinesLeft: true 7 | AlignOperands: false 8 | AlignTrailingComments: false 9 | AllowAllParametersOfDeclarationOnNextLine: false 10 | AllowShortBlocksOnASingleLine: false 11 | AllowShortCaseLabelsOnASingleLine: false 12 | AllowShortFunctionsOnASingleLine: Empty 13 | AllowShortIfStatementsOnASingleLine: false 14 | AllowShortLoopsOnASingleLine: false 15 | AlwaysBreakAfterReturnType: None 16 | AlwaysBreakBeforeMultilineStrings: true 17 | AlwaysBreakTemplateDeclarations: true 18 | BinPackArguments: false 19 | BinPackParameters: false 20 | BraceWrapping: 21 | AfterClass: false 22 | AfterControlStatement: false 23 | AfterEnum: false 24 | AfterFunction: false 25 | AfterNamespace: false 26 | AfterObjCDeclaration: false 27 | AfterStruct: false 28 | AfterUnion: false 29 | BeforeCatch: false 30 | BeforeElse: false 31 | IndentBraces: false 32 | BreakBeforeBinaryOperators: None 33 | BreakBeforeBraces: Attach 34 | BreakBeforeTernaryOperators: true 35 | BreakConstructorInitializersBeforeComma: false 36 | BreakAfterJavaFieldAnnotations: false 37 | BreakStringLiterals: false 38 | ColumnLimit: 80 39 | CommentPragmas: '^ IWYU pragma:' 40 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 41 | ConstructorInitializerIndentWidth: 4 42 | ContinuationIndentWidth: 4 43 | Cpp11BracedListStyle: true 44 | DerivePointerAlignment: false 45 | DisableFormat: false 46 | ForEachMacros: [ FOR_EACH_RANGE, FOR_EACH, ] 47 | IncludeCategories: 48 | - Regex: '^<.*\.h(pp)?>' 49 | Priority: 1 50 | - Regex: '^<.*' 51 | Priority: 2 52 | - Regex: '.*' 53 | Priority: 3 54 | IndentCaseLabels: true 55 | IndentWidth: 2 56 | IndentWrappedFunctionNames: false 57 | KeepEmptyLinesAtTheStartOfBlocks: false 58 | MacroBlockBegin: '' 59 | MacroBlockEnd: '' 60 | MaxEmptyLinesToKeep: 1 61 | NamespaceIndentation: None 62 | ObjCBlockIndentWidth: 2 63 | ObjCSpaceAfterProperty: true 64 | ObjCSpaceBeforeProtocolList: true 65 | PenaltyBreakBeforeFirstCallParameter: 1 66 | PenaltyBreakComment: 300 67 | PenaltyBreakFirstLessLess: 120 68 | PenaltyBreakString: 1000 69 | PenaltyExcessCharacter: 1000000 70 | PenaltyReturnTypeOnItsOwnLine: 200 71 | PointerAlignment: Left 72 | ReflowComments: true 73 | SortIncludes: true 74 | SpaceAfterCStyleCast: false 75 | SpaceBeforeAssignmentOperators: true 76 | SpaceBeforeParens: ControlStatements 77 | SpaceInEmptyParentheses: false 78 | SpacesBeforeTrailingComments: 1 79 | SpacesInAngles: false 80 | SpacesInContainerLiterals: true 81 | SpacesInCStyleCastParentheses: false 82 | SpacesInParentheses: false 83 | SpacesInSquareBrackets: false 84 | Standard: Cpp11 85 | TabWidth: 8 86 | UseTab: Never 87 | --- 88 | Language: ObjC 89 | ColumnLimit: 120 90 | BreakBeforeBraces: WebKit 91 | PointerAlignment: Right 92 | ... 93 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | typings 2 | node_modules 3 | example/android-bundle.js 4 | example/ios-bundle.js 5 | example/web-build 6 | 7 | # generated by bob 8 | dist/ 9 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = {extends: '@react-native'}; 2 | -------------------------------------------------------------------------------- /.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | ; We fork some components by platform 3 | .*/*[.]android.js 4 | .*/*[.]windows.js 5 | 6 | ; Ignore templates for 'react-native init' 7 | /template/.* 8 | 9 | ; Ignore the Dangerfile 10 | /bots/dangerfile.js 11 | 12 | ; Ignore "BUCK" generated dirs 13 | /\.buckd/ 14 | 15 | ; Ignore polyfills 16 | node_modules/react-native/Libraries/polyfills/.* 17 | 18 | ; Flow doesn't support platforms 19 | .*/Libraries/Utilities/LoadingView.js 20 | 21 | .*/node_modules/resolve/test/resolver/malformed_package_json/package\.json$ 22 | 23 | ; Ignore traveling-fastlane-darwin 24 | .*/node_modules/@expo/traveling-fastlane-darwin/.* 25 | 26 | 27 | [untyped] 28 | .*/node_modules/@react-native-community/cli/.*/.* 29 | 30 | [include] 31 | 32 | [declarations] 33 | .*/node_modules/.* 34 | 35 | [libs] 36 | node_modules/react-native/interface.js 37 | node_modules/react-native/flow/ 38 | 39 | [options] 40 | emoji=true 41 | 42 | exact_by_default=true 43 | 44 | format.bracket_spacing=false 45 | 46 | module.file_ext=.js 47 | module.file_ext=.json 48 | module.file_ext=.ios.js 49 | module.file_ext=.web.js 50 | 51 | munge_underscores=true 52 | 53 | module.name_mapper='^react-native/\(.*\)$' -> '/node_modules/react-native/\1' 54 | module.name_mapper='^@?[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> '/node_modules/react-native/Libraries/Image/RelativeImageStub' 55 | 56 | suppress_type=$FlowIssue 57 | suppress_type=$FlowFixMe 58 | suppress_type=$FlowFixMeProps 59 | suppress_type=$FlowFixMeState 60 | 61 | server.max_workers=2 62 | 63 | [lints] 64 | sketchy-null-number=warn 65 | sketchy-null-mixed=warn 66 | sketchy-number=warn 67 | untyped-type-import=warn 68 | nonstrict-import=warn 69 | deprecated-type=warn 70 | unsafe-getters-setters=warn 71 | unnecessary-invariant=warn 72 | 73 | [strict] 74 | deprecated-type 75 | nonstrict-import 76 | sketchy-null 77 | unclear-type 78 | unsafe-getters-setters 79 | untyped-import 80 | untyped-type-import 81 | 82 | [version] 83 | ^0.222.0 84 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @Naturalclar -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | on: 3 | push: 4 | branches: 5 | - 'master' 6 | 7 | jobs: 8 | publish: 9 | runs-on: ubuntu-latest 10 | strategy: 11 | matrix: 12 | node-version: [22] 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v4 16 | with: 17 | fetch-depth: 0 18 | - uses: actions/setup-node@v4 19 | with: 20 | node-version: ${{ matrix.node-version }} 21 | - name: Get yarn cache 22 | id: yarn-cache 23 | run: echo "::set-output name=dir::$(yarn cache dir)" 24 | - uses: actions/cache@v3 25 | with: 26 | path: ${{ steps.yarn-cache.outputs.dir }} 27 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} 28 | - name: Install Dependencies 29 | run: yarn 30 | - name: Publish Package 31 | run: yarn ci:publish 32 | env: 33 | GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} 34 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # OSX 3 | # 4 | .DS_Store 5 | 6 | # node.js 7 | # 8 | node_modules/ 9 | npm-debug.log 10 | yarn-error.log 11 | 12 | 13 | 14 | # Xcode 15 | # 16 | build/ 17 | *.pbxuser 18 | !default.pbxuser 19 | *.mode1v3 20 | !default.mode1v3 21 | *.mode2v3 22 | !default.mode2v3 23 | *.perspectivev3 24 | !default.perspectivev3 25 | xcuserdata 26 | *.xccheckout 27 | *.moved-aside 28 | DerivedData 29 | *.hmap 30 | *.ipa 31 | *.xcuserstate 32 | project.xcworkspace 33 | 34 | 35 | # Android/IntelliJ 36 | # 37 | build/ 38 | .idea 39 | .gradle 40 | local.properties 41 | *.iml 42 | 43 | # BUCK 44 | buck-out/ 45 | \.buckd/ 46 | 47 | # Editor config 48 | .vscode 49 | 50 | # Outputs 51 | coverage 52 | 53 | .tmp 54 | example/android-bundle.js 55 | example/ios-bundle.js 56 | index.android.bundle 57 | index.ios.bundle 58 | 59 | # CocoaPods 60 | /ios/Pods/ 61 | example/ios/Pods/ 62 | 63 | # Android generated code 64 | .project 65 | .settings 66 | .classpath 67 | 68 | # expo generated files 69 | .expo 70 | web-build 71 | 72 | # MSBuild logs 73 | *.binlog 74 | 75 | # generated by bob 76 | dist/ 77 | 78 | # yarn files 79 | .yarn 80 | !.yarn/releases 81 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | /screenshots 2 | __tests__ 3 | /example 4 | /e2e 5 | /.circleci 6 | /webpack.config.js 7 | /app.config.js 8 | /.expo -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all", 4 | "bracketSpacing": false, 5 | "jsxBracketSameLine": true, 6 | "parser": "flow" 7 | } -------------------------------------------------------------------------------- /.releaserc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "@semantic-release/commit-analyzer", 4 | "@semantic-release/release-notes-generator", 5 | "@semantic-release/npm", 6 | "@semantic-release/github", 7 | [ 8 | "@semantic-release/git", 9 | { 10 | "assets": "package.json", 11 | "message": "chore(release): ${nextRelease.version} [skip ci] \n\n${nextRelease.notes}" 12 | } 13 | ] 14 | ] 15 | } 16 | 17 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | compressionLevel: mixed 2 | 3 | enableGlobalCache: false 4 | 5 | nodeLinker: node-modules 6 | 7 | yarnPath: .yarn/releases/yarn-4.1.1.cjs 8 | -------------------------------------------------------------------------------- /FabricExample/.bundle/config: -------------------------------------------------------------------------------- 1 | BUNDLE_PATH: "vendor/bundle" 2 | BUNDLE_FORCE_RUBY_PLATFORM: 1 3 | -------------------------------------------------------------------------------- /FabricExample/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: '@react-native', 4 | }; 5 | -------------------------------------------------------------------------------- /FabricExample/.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 | **/.xcode.env.local 24 | 25 | # Android/IntelliJ 26 | # 27 | build/ 28 | .idea 29 | .gradle 30 | local.properties 31 | *.iml 32 | *.hprof 33 | .cxx/ 34 | *.keystore 35 | !debug.keystore 36 | 37 | # node.js 38 | # 39 | node_modules/ 40 | npm-debug.log 41 | yarn-error.log 42 | 43 | # fastlane 44 | # 45 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 46 | # screenshots whenever they are needed. 47 | # For more information about the recommended setup visit: 48 | # https://docs.fastlane.tools/best-practices/source-control/ 49 | 50 | **/fastlane/report.xml 51 | **/fastlane/Preview.html 52 | **/fastlane/screenshots 53 | **/fastlane/test_output 54 | 55 | # Bundle artifact 56 | *.jsbundle 57 | 58 | # Ruby / CocoaPods 59 | **/Pods/ 60 | /vendor/bundle/ 61 | 62 | # Temporary files created by Metro to check the health of the file watcher 63 | .metro-health-check* 64 | 65 | # testing 66 | /coverage 67 | 68 | .yarn/* 69 | !.yarn/patches 70 | !.yarn/plugins 71 | !.yarn/releases 72 | !.yarn/sdks 73 | !.yarn/versions 74 | -------------------------------------------------------------------------------- /FabricExample/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | arrowParens: 'avoid', 3 | bracketSameLine: true, 4 | bracketSpacing: false, 5 | singleQuote: true, 6 | trailingComma: 'all', 7 | }; 8 | -------------------------------------------------------------------------------- /FabricExample/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /FabricExample/App.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { 3 | Platform, 4 | ScrollView, 5 | StyleSheet, 6 | Text, 7 | View, 8 | SafeAreaView, 9 | I18nManager, 10 | Switch, 11 | } from 'react-native'; 12 | 13 | import * as PickerExamples from './PickerExample'; 14 | import * as PickerIOSExamples from './PickerIOSExample'; 15 | 16 | export default function App() { 17 | const [isRTL, setIsRTL] = React.useState(I18nManager.isRTL); 18 | React.useEffect(() => { 19 | I18nManager.allowRTL(true); 20 | }, []); 21 | 22 | return ( 23 | 24 | 25 | 26 | { 29 | setIsRTL(newValue); 30 | I18nManager.forceRTL(newValue); 31 | }} 32 | /> 33 | {I18nManager.isRTL ? 'RTL' : 'LTR'} 34 | 35 | 36 | Picker Examples 37 | {PickerExamples.examples.map(element => ( 38 | 39 | {element.title} 40 | {element.render()} 41 | 42 | ))} 43 | {Platform.OS === 'ios' && ( 44 | PickerIOS Examples 45 | )} 46 | {Platform.OS === 'ios' && 47 | PickerIOSExamples.examples.map(element => ( 48 | 49 | {element.title} 50 | {element.render()} 51 | 52 | ))} 53 | {Platform.OS === 'windows' && ( 54 | PickerWindows Examples 55 | )} 56 | 57 | 58 | 59 | ); 60 | } 61 | 62 | const styles = StyleSheet.create({ 63 | main: { 64 | backgroundColor: '#F5FCFF', 65 | }, 66 | container: { 67 | padding: 24, 68 | paddingBottom: 60, 69 | }, 70 | title: { 71 | fontSize: 18, 72 | }, 73 | elementContainer: { 74 | marginTop: 8, 75 | }, 76 | heading: { 77 | fontSize: 22, 78 | color: 'black', 79 | }, 80 | rtlSwitchContainer: { 81 | flexDirection: 'row', 82 | justifyContent: 'space-between', 83 | paddingHorizontal: 40, 84 | paddingTop: 20, 85 | }, 86 | }); 87 | -------------------------------------------------------------------------------- /FabricExample/Gemfile: -------------------------------------------------------------------------------- 1 | # You may use http://rbenv.org/ or https://rvm.io/ to install and use this version 2 | ruby ">= 2.6.10" 3 | 4 | # Exclude problematic versions of cocoapods and activesupport that causes build failures. 5 | gem 'cocoapods', '>= 1.13', '!= 1.15.0', '!= 1.15.1' 6 | gem 'activesupport', '>= 6.1.7.5', '!= 7.1.0' 7 | -------------------------------------------------------------------------------- /FabricExample/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | CFPropertyList (3.0.6) 5 | rexml 6 | activesupport (7.0.8) 7 | concurrent-ruby (~> 1.0, >= 1.0.2) 8 | i18n (>= 1.6, < 2) 9 | minitest (>= 5.1) 10 | tzinfo (~> 2.0) 11 | addressable (2.8.5) 12 | public_suffix (>= 2.0.2, < 6.0) 13 | algoliasearch (1.27.5) 14 | httpclient (~> 2.8, >= 2.8.3) 15 | json (>= 1.5.1) 16 | atomos (0.1.3) 17 | claide (1.1.0) 18 | cocoapods (1.14.3) 19 | addressable (~> 2.8) 20 | claide (>= 1.0.2, < 2.0) 21 | cocoapods-core (= 1.14.3) 22 | cocoapods-deintegrate (>= 1.0.3, < 2.0) 23 | cocoapods-downloader (>= 2.1, < 3.0) 24 | cocoapods-plugins (>= 1.0.0, < 2.0) 25 | cocoapods-search (>= 1.0.0, < 2.0) 26 | cocoapods-trunk (>= 1.6.0, < 2.0) 27 | cocoapods-try (>= 1.1.0, < 2.0) 28 | colored2 (~> 3.1) 29 | escape (~> 0.0.4) 30 | fourflusher (>= 2.3.0, < 3.0) 31 | gh_inspector (~> 1.0) 32 | molinillo (~> 0.8.0) 33 | nap (~> 1.0) 34 | ruby-macho (>= 2.3.0, < 3.0) 35 | xcodeproj (>= 1.23.0, < 2.0) 36 | cocoapods-core (1.14.3) 37 | activesupport (>= 5.0, < 8) 38 | addressable (~> 2.8) 39 | algoliasearch (~> 1.0) 40 | concurrent-ruby (~> 1.1) 41 | fuzzy_match (~> 2.0.4) 42 | nap (~> 1.0) 43 | netrc (~> 0.11) 44 | public_suffix (~> 4.0) 45 | typhoeus (~> 1.0) 46 | cocoapods-deintegrate (1.0.5) 47 | cocoapods-downloader (2.1) 48 | cocoapods-plugins (1.0.0) 49 | nap 50 | cocoapods-search (1.0.1) 51 | cocoapods-trunk (1.6.0) 52 | nap (>= 0.8, < 2.0) 53 | netrc (~> 0.11) 54 | cocoapods-try (1.2.0) 55 | colored2 (3.1.2) 56 | concurrent-ruby (1.2.2) 57 | escape (0.0.4) 58 | ethon (0.16.0) 59 | ffi (>= 1.15.0) 60 | ffi (1.16.3) 61 | fourflusher (2.3.1) 62 | fuzzy_match (2.0.4) 63 | gh_inspector (1.1.3) 64 | httpclient (2.8.3) 65 | i18n (1.14.1) 66 | concurrent-ruby (~> 1.0) 67 | json (2.6.3) 68 | minitest (5.20.0) 69 | molinillo (0.8.0) 70 | nanaimo (0.3.0) 71 | nap (1.1.0) 72 | netrc (0.11.0) 73 | public_suffix (4.0.7) 74 | rexml (3.2.6) 75 | ruby-macho (2.5.1) 76 | typhoeus (1.4.1) 77 | ethon (>= 0.9.0) 78 | tzinfo (2.0.6) 79 | concurrent-ruby (~> 1.0) 80 | xcodeproj (1.23.0) 81 | CFPropertyList (>= 2.3.3, < 4.0) 82 | atomos (~> 0.1.3) 83 | claide (>= 1.0.2, < 2.0) 84 | colored2 (~> 3.1) 85 | nanaimo (~> 0.3.0) 86 | rexml (~> 3.2.4) 87 | 88 | PLATFORMS 89 | ruby 90 | 91 | DEPENDENCIES 92 | activesupport (>= 6.1.7.3, < 7.1.0) 93 | cocoapods (~> 1.13) 94 | 95 | RUBY VERSION 96 | ruby 2.7.5p203 97 | 98 | BUNDLED WITH 99 | 2.1.4 100 | -------------------------------------------------------------------------------- /FabricExample/PickerWindowsExamples.js: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import {View} from 'react-native'; 3 | import {Picker} from '@react-native-picker/picker'; 4 | 5 | const Item: any = Picker.Item; 6 | 7 | function PlaceholderPickerExample() { 8 | return ( 9 | 10 | 11 | 12 | 13 | 14 | 15 | ); 16 | } 17 | 18 | export const examples = [ 19 | { 20 | title: 'Picker with placeholder', 21 | render: PlaceholderPickerExample, 22 | }, 23 | ]; 24 | -------------------------------------------------------------------------------- /FabricExample/README.md: -------------------------------------------------------------------------------- 1 | This is a new [**React Native**](https://reactnative.dev) project, bootstrapped using [`@react-native-community/cli`](https://github.com/react-native-community/cli). 2 | 3 | # Getting Started 4 | 5 | >**Note**: Make sure you have completed the [React Native - Environment Setup](https://reactnative.dev/docs/environment-setup) instructions till "Creating a new application" step, before proceeding. 6 | 7 | ## Step 1: Start the Metro Server 8 | 9 | First, you will need to start **Metro**, the JavaScript _bundler_ that ships _with_ React Native. 10 | 11 | To start Metro, run the following command from the _root_ of your React Native project: 12 | 13 | ```bash 14 | # using npm 15 | npm start 16 | 17 | # OR using Yarn 18 | yarn start 19 | ``` 20 | 21 | ## Step 2: Start your Application 22 | 23 | Let Metro Bundler run in its _own_ terminal. Open a _new_ terminal from the _root_ of your React Native project. Run the following command to start your _Android_ or _iOS_ app: 24 | 25 | ### For Android 26 | 27 | ```bash 28 | # using npm 29 | npm run android 30 | 31 | # OR using Yarn 32 | yarn android 33 | ``` 34 | 35 | ### For iOS 36 | 37 | ```bash 38 | # using npm 39 | npm run ios 40 | 41 | # OR using Yarn 42 | yarn ios 43 | ``` 44 | 45 | If everything is set up _correctly_, you should see your new app running in your _Android Emulator_ or _iOS Simulator_ shortly provided you have set up your emulator/simulator correctly. 46 | 47 | This is one way to run your app — you can also run it directly from within Android Studio and Xcode respectively. 48 | 49 | ## Step 3: Modifying your App 50 | 51 | Now that you have successfully run the app, let's modify it. 52 | 53 | 1. Open `App.tsx` in your text editor of choice and edit some lines. 54 | 2. For **Android**: Press the R key twice or select **"Reload"** from the **Developer Menu** (Ctrl + M (on Window and Linux) or Cmd ⌘ + M (on macOS)) to see your changes! 55 | 56 | For **iOS**: Hit Cmd ⌘ + R in your iOS Simulator to reload the app and see your changes! 57 | 58 | ## Congratulations! :tada: 59 | 60 | You've successfully run and modified your React Native App. :partying_face: 61 | 62 | ### Now what? 63 | 64 | - If you want to add this new React Native code to an existing application, check out the [Integration guide](https://reactnative.dev/docs/integration-with-existing-apps). 65 | - If you're curious to learn more about React Native, check out the [Introduction to React Native](https://reactnative.dev/docs/getting-started). 66 | 67 | # Troubleshooting 68 | 69 | If you can't get this to work, see the [Troubleshooting](https://reactnative.dev/docs/troubleshooting) page. 70 | 71 | # Learn More 72 | 73 | To learn more about React Native, take a look at the following resources: 74 | 75 | - [React Native Website](https://reactnative.dev) - learn more about React Native. 76 | - [Getting Started](https://reactnative.dev/docs/environment-setup) - an **overview** of React Native and how setup your environment. 77 | - [Learn the Basics](https://reactnative.dev/docs/getting-started) - a **guided tour** of the React Native **basics**. 78 | - [Blog](https://reactnative.dev/blog) - read the latest official React Native **Blog** posts. 79 | - [`@facebook/react-native`](https://github.com/facebook/react-native) - the Open Source; GitHub **repository** for React Native. 80 | -------------------------------------------------------------------------------- /FabricExample/__tests__/App.test.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import 'react-native'; 6 | import React from 'react'; 7 | import App from '../App'; 8 | 9 | // Note: import explicitly to use the types shipped with jest. 10 | import {it} from '@jest/globals'; 11 | 12 | // Note: test renderer must be required after react-native. 13 | import renderer from 'react-test-renderer'; 14 | 15 | it('renders correctly', () => { 16 | renderer.create(); 17 | }); 18 | -------------------------------------------------------------------------------- /FabricExample/android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/react-native-picker/picker/11cade13725af12bb79c55769ca80f0f772dd95e/FabricExample/android/app/debug.keystore -------------------------------------------------------------------------------- /FabricExample/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 | -------------------------------------------------------------------------------- /FabricExample/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | -------------------------------------------------------------------------------- /FabricExample/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /FabricExample/android/app/src/main/java/com/fabricexample/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.fabricexample 2 | 3 | import com.facebook.react.ReactActivity 4 | import com.facebook.react.ReactActivityDelegate 5 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled 6 | import com.facebook.react.defaults.DefaultReactActivityDelegate 7 | 8 | class MainActivity : ReactActivity() { 9 | 10 | /** 11 | * Returns the name of the main component registered from JavaScript. This is used to schedule 12 | * rendering of the component. 13 | */ 14 | override fun getMainComponentName(): String = "FabricExample" 15 | 16 | /** 17 | * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate] 18 | * which allows you to enable New Architecture with a single boolean flags [fabricEnabled] 19 | */ 20 | override fun createReactActivityDelegate(): ReactActivityDelegate = 21 | DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled) 22 | } 23 | -------------------------------------------------------------------------------- /FabricExample/android/app/src/main/java/com/fabricexample/MainApplication.kt: -------------------------------------------------------------------------------- 1 | package com.fabricexample 2 | 3 | import android.app.Application 4 | import com.facebook.react.PackageList 5 | import com.facebook.react.ReactApplication 6 | import com.facebook.react.ReactHost 7 | import com.facebook.react.ReactNativeHost 8 | import com.facebook.react.ReactPackage 9 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load 10 | import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost 11 | import com.facebook.react.defaults.DefaultReactNativeHost 12 | import com.facebook.react.soloader.OpenSourceMergedSoMapping 13 | import com.facebook.soloader.SoLoader 14 | 15 | class MainApplication : Application(), ReactApplication { 16 | 17 | override val reactNativeHost: ReactNativeHost = 18 | object : DefaultReactNativeHost(this) { 19 | override fun getPackages(): List = 20 | PackageList(this).packages.apply { 21 | // Packages that cannot be autolinked yet can be added manually here, for example: 22 | // add(MyReactNativePackage()) 23 | } 24 | 25 | override fun getJSMainModuleName(): String = "index" 26 | 27 | override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG 28 | 29 | override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED 30 | override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED 31 | } 32 | 33 | override val reactHost: ReactHost 34 | get() = getDefaultReactHost(applicationContext, reactNativeHost) 35 | 36 | override fun onCreate() { 37 | super.onCreate() 38 | SoLoader.init(this, OpenSourceMergedSoMapping) 39 | if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { 40 | // If you opted-in for the New Architecture, we load the native entry point for this app. 41 | load() 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /FabricExample/android/app/src/main/res/drawable/rn_edit_text_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 22 | 23 | 24 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /FabricExample/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/react-native-picker/picker/11cade13725af12bb79c55769ca80f0f772dd95e/FabricExample/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /FabricExample/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/react-native-picker/picker/11cade13725af12bb79c55769ca80f0f772dd95e/FabricExample/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /FabricExample/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/react-native-picker/picker/11cade13725af12bb79c55769ca80f0f772dd95e/FabricExample/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /FabricExample/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/react-native-picker/picker/11cade13725af12bb79c55769ca80f0f772dd95e/FabricExample/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /FabricExample/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/react-native-picker/picker/11cade13725af12bb79c55769ca80f0f772dd95e/FabricExample/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /FabricExample/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/react-native-picker/picker/11cade13725af12bb79c55769ca80f0f772dd95e/FabricExample/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /FabricExample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/react-native-picker/picker/11cade13725af12bb79c55769ca80f0f772dd95e/FabricExample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /FabricExample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/react-native-picker/picker/11cade13725af12bb79c55769ca80f0f772dd95e/FabricExample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /FabricExample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/react-native-picker/picker/11cade13725af12bb79c55769ca80f0f772dd95e/FabricExample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /FabricExample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/react-native-picker/picker/11cade13725af12bb79c55769ca80f0f772dd95e/FabricExample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /FabricExample/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | FabricExample 3 | 4 | -------------------------------------------------------------------------------- /FabricExample/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /FabricExample/android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext { 5 | buildToolsVersion = "35.0.0" 6 | minSdkVersion = 24 7 | compileSdkVersion = 35 8 | targetSdkVersion = 34 9 | 10 | ndkVersion = "26.1.10909125" 11 | kotlinVersion = "1.9.24" 12 | } 13 | repositories { 14 | google() 15 | mavenCentral() 16 | } 17 | dependencies { 18 | classpath("com.android.tools.build:gradle") 19 | classpath("com.facebook.react:react-native-gradle-plugin") 20 | classpath("org.jetbrains.kotlin:kotlin-gradle-plugin") 21 | } 22 | } 23 | 24 | apply plugin: "com.facebook.react.rootproject" 25 | -------------------------------------------------------------------------------- /FabricExample/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: -Xmx512m -XX:MaxMetaspaceSize=256m 13 | org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m 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 | # AndroidX package structure to make it clearer which packages are bundled with the 21 | # Android operating system, and which are packaged with your app's APK 22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 23 | android.useAndroidX=true 24 | # Automatically convert third-party libraries to use AndroidX 25 | android.enableJetifier=true 26 | 27 | # Use this property to specify which architecture you want to build. 28 | # You can also override it from the CLI using 29 | # ./gradlew -PreactNativeArchitectures=x86_64 30 | reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 31 | 32 | # Use this property to enable support to the new architecture. 33 | # This will allow you to use TurboModules and the Fabric render in 34 | # your application. You should enable this flag either if you want 35 | # to write custom TurboModules/Fabric components OR use libraries that 36 | # are providing them. 37 | newArchEnabled=true 38 | 39 | # Use this property to enable or disable the Hermes JS engine. 40 | # If set to false, you will be using JSC instead. 41 | hermesEnabled=true 42 | -------------------------------------------------------------------------------- /FabricExample/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/react-native-picker/picker/11cade13725af12bb79c55769ca80f0f772dd95e/FabricExample/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /FabricExample/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /FabricExample/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | @rem This is normally unused 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem Find java.exe 40 | if defined JAVA_HOME goto findJavaFromJavaHome 41 | 42 | set JAVA_EXE=java.exe 43 | %JAVA_EXE% -version >NUL 2>&1 44 | if %ERRORLEVEL% equ 0 goto execute 45 | 46 | echo. 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 48 | echo. 49 | echo Please set the JAVA_HOME variable in your environment to match the 50 | echo location of your Java installation. 51 | 52 | goto fail 53 | 54 | :findJavaFromJavaHome 55 | set JAVA_HOME=%JAVA_HOME:"=% 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 57 | 58 | if exist "%JAVA_EXE%" goto execute 59 | 60 | echo. 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 62 | echo. 63 | echo Please set the JAVA_HOME variable in your environment to match the 64 | echo location of your Java installation. 65 | 66 | goto fail 67 | 68 | :execute 69 | @rem Setup the command line 70 | 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 72 | 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 %* 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if %ERRORLEVEL% equ 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 | set EXIT_CODE=%ERRORLEVEL% 85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 87 | exit /b %EXIT_CODE% 88 | 89 | :mainEnd 90 | if "%OS%"=="Windows_NT" endlocal 91 | 92 | :omega 93 | -------------------------------------------------------------------------------- /FabricExample/android/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { includeBuild("../node_modules/@react-native/gradle-plugin") } 2 | plugins { id("com.facebook.react.settings") } 3 | extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() } 4 | rootProject.name = 'FabricExample' 5 | include ':app' 6 | includeBuild('../node_modules/@react-native/gradle-plugin') 7 | -------------------------------------------------------------------------------- /FabricExample/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "FabricExample", 3 | "displayName": "FabricExample" 4 | } 5 | -------------------------------------------------------------------------------- /FabricExample/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:@react-native/babel-preset'], 3 | }; 4 | -------------------------------------------------------------------------------- /FabricExample/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import {AppRegistry} from 'react-native'; 6 | import App from './App'; 7 | import {name as appName} from './app.json'; 8 | 9 | AppRegistry.registerComponent(appName, () => App); 10 | -------------------------------------------------------------------------------- /FabricExample/ios/.xcode.env: -------------------------------------------------------------------------------- 1 | # This `.xcode.env` file is versioned and is used to source the environment 2 | # used when running script phases inside Xcode. 3 | # To customize your local environment, you can create an `.xcode.env.local` 4 | # file that is not versioned. 5 | 6 | # NODE_BINARY variable contains the PATH to the node executable. 7 | # 8 | # Customize the NODE_BINARY variable here. 9 | # For example, to use nvm with brew, add the following line 10 | # . "$(brew --prefix nvm)/nvm.sh" --no-use 11 | export NODE_BINARY=$(command -v node) 12 | -------------------------------------------------------------------------------- /FabricExample/ios/FabricExample.xcodeproj/xcshareddata/xcschemes/FabricExample.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 53 | 55 | 61 | 62 | 63 | 64 | 70 | 72 | 78 | 79 | 80 | 81 | 83 | 84 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /FabricExample/ios/FabricExample.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /FabricExample/ios/FabricExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /FabricExample/ios/FabricExample/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : RCTAppDelegate 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /FabricExample/ios/FabricExample/AppDelegate.mm: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | 3 | #import 4 | 5 | @implementation AppDelegate 6 | 7 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 8 | { 9 | self.moduleName = @"FabricExample"; 10 | // You can add your custom initial props in the dictionary below. 11 | // They will be passed down to the ViewController used by React Native. 12 | self.initialProps = @{}; 13 | 14 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 15 | } 16 | 17 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge 18 | { 19 | return [self bundleURL]; 20 | } 21 | 22 | - (BOOL)bridgelessEnabled { 23 | return true; 24 | } 25 | 26 | - (NSURL *)bundleURL 27 | { 28 | #if DEBUG 29 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"]; 30 | #else 31 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; 32 | #endif 33 | } 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /FabricExample/ios/FabricExample/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ios-marketing", 45 | "scale" : "1x", 46 | "size" : "1024x1024" 47 | } 48 | ], 49 | "info" : { 50 | "author" : "xcode", 51 | "version" : 1 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /FabricExample/ios/FabricExample/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /FabricExample/ios/FabricExample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | FabricExample 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(MARKETING_VERSION) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(CURRENT_PROJECT_VERSION) 25 | LSRequiresIPhoneOS 26 | 27 | NSAppTransportSecurity 28 | 29 | NSAllowsArbitraryLoads 30 | 31 | NSAllowsLocalNetworking 32 | 33 | 34 | NSLocationWhenInUseUsageDescription 35 | 36 | UILaunchStoryboardName 37 | LaunchScreen 38 | UIRequiredDeviceCapabilities 39 | 40 | arm64 41 | 42 | UISupportedInterfaceOrientations 43 | 44 | UIInterfaceOrientationPortrait 45 | UIInterfaceOrientationLandscapeLeft 46 | UIInterfaceOrientationLandscapeRight 47 | 48 | UIViewControllerBasedStatusBarAppearance 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /FabricExample/ios/FabricExample/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 24 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /FabricExample/ios/FabricExample/PrivacyInfo.xcprivacy: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSPrivacyAccessedAPITypes 6 | 7 | 8 | NSPrivacyAccessedAPIType 9 | NSPrivacyAccessedAPICategoryFileTimestamp 10 | NSPrivacyAccessedAPITypeReasons 11 | 12 | C617.1 13 | 14 | 15 | 16 | NSPrivacyAccessedAPIType 17 | NSPrivacyAccessedAPICategoryUserDefaults 18 | NSPrivacyAccessedAPITypeReasons 19 | 20 | CA92.1 21 | 22 | 23 | 24 | NSPrivacyAccessedAPIType 25 | NSPrivacyAccessedAPICategorySystemBootTime 26 | NSPrivacyAccessedAPITypeReasons 27 | 28 | 35F9.1 29 | 30 | 31 | 32 | NSPrivacyCollectedDataTypes 33 | 34 | NSPrivacyTracking 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /FabricExample/ios/FabricExample/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | @autoreleasepool { 8 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /FabricExample/ios/FabricExampleTests/FabricExampleTests.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | #import 5 | #import 6 | 7 | #define TIMEOUT_SECONDS 600 8 | #define TEXT_TO_LOOK_FOR @"Welcome to React" 9 | 10 | @interface FabricExampleTests : XCTestCase 11 | 12 | @end 13 | 14 | @implementation FabricExampleTests 15 | 16 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL (^)(UIView *view))test 17 | { 18 | if (test(view)) { 19 | return YES; 20 | } 21 | for (UIView *subview in [view subviews]) { 22 | if ([self findSubviewInView:subview matching:test]) { 23 | return YES; 24 | } 25 | } 26 | return NO; 27 | } 28 | 29 | - (void)testRendersWelcomeScreen 30 | { 31 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; 32 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; 33 | BOOL foundElement = NO; 34 | 35 | __block NSString *redboxError = nil; 36 | #ifdef DEBUG 37 | RCTSetLogFunction( 38 | ^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { 39 | if (level >= RCTLogLevelError) { 40 | redboxError = message; 41 | } 42 | }); 43 | #endif 44 | 45 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { 46 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 47 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 48 | 49 | foundElement = [self findSubviewInView:vc.view 50 | matching:^BOOL(UIView *view) { 51 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { 52 | return YES; 53 | } 54 | return NO; 55 | }]; 56 | } 57 | 58 | #ifdef DEBUG 59 | RCTSetLogFunction(RCTDefaultLogFunction); 60 | #endif 61 | 62 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); 63 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); 64 | } 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /FabricExample/ios/FabricExampleTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /FabricExample/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Resolve react_native_pods.rb with node to allow for hoisting 2 | require Pod::Executable.execute_command('node', ['-p', 3 | 'require.resolve( 4 | "react-native/scripts/react_native_pods.rb", 5 | {paths: [process.argv[1]]}, 6 | )', __dir__]).strip 7 | 8 | platform :ios, min_ios_version_supported 9 | prepare_react_native_project! 10 | 11 | linkage = ENV['USE_FRAMEWORKS'] 12 | if linkage != nil 13 | Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green 14 | use_frameworks! :linkage => linkage.to_sym 15 | end 16 | 17 | target 'FabricExample' do 18 | config = use_native_modules! 19 | 20 | use_react_native!( 21 | :path => config[:reactNativePath], 22 | # An absolute path to your application root. 23 | :app_path => "#{Pod::Config.instance.installation_root}/.." 24 | ) 25 | 26 | target 'FabricExampleTests' do 27 | inherit! :complete 28 | # Pods for testing 29 | end 30 | 31 | post_install do |installer| 32 | # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202 33 | react_native_post_install( 34 | installer, 35 | config[:reactNativePath], 36 | :mac_catalyst_enabled => false, 37 | # :ccache_enabled => true 38 | ) 39 | end 40 | end -------------------------------------------------------------------------------- /FabricExample/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'react-native', 3 | }; 4 | -------------------------------------------------------------------------------- /FabricExample/metro.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Metro configuration for React Native 3 | * https://reactnative.dev/docs/metro 4 | * 5 | * @format 6 | */ 7 | 8 | const {getDefaultConfig} = require('@react-native/metro-config'); 9 | const {mergeConfig} = require('metro-config'); 10 | 11 | const path = require('path'); 12 | const exclusionList = require('metro-config/src/defaults/exclusionList'); 13 | const escape = require('escape-string-regexp'); 14 | const pack = require('../package.json'); 15 | 16 | const root = path.resolve(__dirname, '..'); 17 | 18 | const modules = Object.keys(pack.peerDependencies); 19 | 20 | const config = { 21 | projectRoot: __dirname, 22 | watchFolders: [root], 23 | 24 | // We need to make sure that only one version is loaded for peerDependencies 25 | // So we exclude them at the root, and alias them to the versions in example's node_modules 26 | resolver: { 27 | blacklistRE: exclusionList( 28 | modules.map( 29 | m => new RegExp(`^${escape(path.join(root, 'node_modules', m))}\\/.*$`), 30 | ), 31 | ), 32 | 33 | extraNodeModules: modules.reduce((acc, name) => { 34 | acc[name] = path.join(__dirname, 'node_modules', name); 35 | return acc; 36 | }, {}), 37 | }, 38 | 39 | transformer: { 40 | getTransformOptions: async () => ({ 41 | transform: { 42 | experimentalImportSupport: false, 43 | inlineRequires: true, 44 | }, 45 | }), 46 | }, 47 | }; 48 | 49 | module.exports = mergeConfig(getDefaultConfig(__dirname), config); 50 | -------------------------------------------------------------------------------- /FabricExample/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "FabricExample", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "android": "react-native run-android", 7 | "ios": "react-native run-ios", 8 | "lint": "eslint .", 9 | "start": "react-native start", 10 | "test": "jest" 11 | }, 12 | "dependencies": { 13 | "@react-native-picker/picker": "link:../", 14 | "react": "18.3.1", 15 | "react-native": "0.76.0" 16 | }, 17 | "devDependencies": { 18 | "@babel/core": "^7.25.2", 19 | "@babel/preset-env": "^7.25.3", 20 | "@babel/runtime": "^7.25.0", 21 | "@react-native-community/cli": "15.0.0-alpha.2", 22 | "@react-native-community/cli-platform-android": "15.0.0-alpha.2", 23 | "@react-native-community/cli-platform-ios": "15.0.0-alpha.2", 24 | "@react-native/babel-preset": "0.76.0", 25 | "@react-native/eslint-config": "0.76.0", 26 | "@react-native/metro-config": "0.76.0", 27 | "@react-native/typescript-config": "0.76.0", 28 | "@types/react": "^18.2.6", 29 | "@types/react-test-renderer": "^18.0.0", 30 | "babel-jest": "^29.6.3", 31 | "eslint": "^8.19.0", 32 | "jest": "^29.6.3", 33 | "prettier": "2.8.8", 34 | "react-test-renderer": "18.3.1", 35 | "typescript": "5.0.4" 36 | }, 37 | "engines": { 38 | "node": ">=18" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /FabricExample/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@react-native/typescript-config/tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2015-present, Facebook, Inc. 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 | -------------------------------------------------------------------------------- /RNCPicker.podspec: -------------------------------------------------------------------------------- 1 | require 'json' 2 | 3 | fabric_enabled = ENV['RCT_NEW_ARCH_ENABLED'] == '1' 4 | 5 | package = JSON.parse(File.read(File.join(__dir__, 'package.json'))) 6 | 7 | Pod::Spec.new do |s| 8 | s.name = "RNCPicker" 9 | s.version = package['version'] 10 | s.summary = package['description'] 11 | s.license = package['license'] 12 | 13 | s.authors = package['author'] 14 | s.homepage = package['homepage'] 15 | s.platforms = { :ios => "9.0", :osx => "10.14" } 16 | 17 | s.source = { :git => "https://github.com/react-native-picker/picker.git", :tag => "v#{s.version}" } 18 | 19 | if fabric_enabled 20 | s.platforms = { ios: '11.0', tvos: '11.0' } 21 | s.source_files = 'ios/**/*.{h,m,mm,cpp}' 22 | s.requires_arc = true 23 | 24 | install_modules_dependencies(s) 25 | else 26 | s.ios.source_files = "ios/**/*.{h,m,mm}" 27 | s.osx.source_files = "macos/**/*.{h,m,mm}" 28 | end 29 | 30 | s.dependency 'React-Core' 31 | end 32 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | 2 | buildscript { 3 | ext.safeExtGet = {prop, fallback -> 4 | rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback 5 | } 6 | repositories { 7 | google() 8 | mavenCentral() 9 | } 10 | 11 | dependencies { 12 | classpath("com.android.tools.build:gradle:7.2.0") 13 | } 14 | } 15 | 16 | def getExtOrDefault(name) { 17 | return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties['ReactNativePicker_' + name] 18 | } 19 | 20 | def getExtOrIntegerDefault(name) { 21 | return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties['ReactNativePicker_' + name]).toInteger() 22 | } 23 | 24 | 25 | def resolveReactNativeDirectory() { 26 | def reactNativeLocation = safeExtGet("REACT_NATIVE_NODE_MODULES_DIR", null) 27 | if (reactNativeLocation != null) { 28 | return file(reactNativeLocation) 29 | } 30 | 31 | // monorepo workaround 32 | // react-native can be hoisted or in project's own node_modules 33 | def reactNativeFromProjectNodeModules = file("${rootProject.projectDir}/../node_modules/react-native") 34 | if (reactNativeFromProjectNodeModules.exists()) { 35 | return reactNativeFromProjectNodeModules 36 | } 37 | 38 | def reactNativeFromNodeModulesWithPicker = file("${projectDir}/../../../react-native") 39 | if (reactNativeFromNodeModulesWithPicker.exists()) { 40 | return reactNativeFromNodeModulesWithPicker 41 | } 42 | 43 | throw new Exception( 44 | "[react-native-picker] Unable to resolve react-native location in " + 45 | "node_modules. You should add project extension property (in app/build.gradle) " + 46 | "`REACT_NATIVE_NODE_MODULES_DIR` with path to react-native." 47 | ) 48 | } 49 | 50 | def getReactNativeMinorVersion() { 51 | def REACT_NATIVE_DIR = resolveReactNativeDirectory() 52 | 53 | def reactProperties = new Properties() 54 | file("$REACT_NATIVE_DIR/ReactAndroid/gradle.properties").withInputStream { reactProperties.load(it) } 55 | 56 | def REACT_NATIVE_VERSION = reactProperties.getProperty("VERSION_NAME") 57 | def REACT_NATIVE_MINOR_VERSION = REACT_NATIVE_VERSION.startsWith("0.0.0-") ? 1000 : REACT_NATIVE_VERSION.split("\\.")[1].toInteger() 58 | 59 | return REACT_NATIVE_MINOR_VERSION 60 | } 61 | 62 | def isNewArchitectureEnabled() { 63 | // To opt-in for the New Architecture, you can either: 64 | // - Set `newArchEnabled` to true inside the `gradle.properties` file 65 | // - Invoke gradle with `-newArchEnabled=true` 66 | // - Set an environment variable `ORG_GRADLE_PROJECT_newArchEnabled=true` 67 | return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true" 68 | } 69 | 70 | apply plugin: 'com.android.library' 71 | 72 | if (isNewArchitectureEnabled()) { 73 | apply plugin: "com.facebook.react" 74 | } 75 | 76 | android { 77 | def agpVersion = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION 78 | if (agpVersion.tokenize('.')[0].toInteger() >= 7) { 79 | namespace "com.reactnativecommunity.picker" 80 | } 81 | 82 | compileSdkVersion safeExtGet('compileSdkVersion', 31) 83 | 84 | defaultConfig { 85 | minSdkVersion safeExtGet('minSdkVersion', 21) 86 | targetSdkVersion safeExtGet('targetSdkVersion', 31) 87 | vectorDrawables.useSupportLibrary=getExtOrDefault('vector_drawable_use_support_library') 88 | buildConfigField("boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()) 89 | } 90 | 91 | sourceSets.main { 92 | java { 93 | if (isNewArchitectureEnabled()) { 94 | srcDirs += [ 95 | "src/fabric/java", 96 | ] 97 | } else { 98 | srcDirs += [ 99 | "src/paper/java", 100 | ] 101 | } 102 | } 103 | } 104 | } 105 | 106 | repositories { 107 | maven { 108 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 109 | url "$projectDir/../node_modules/react-native/android" 110 | } 111 | google() 112 | mavenCentral() 113 | } 114 | 115 | dependencies { 116 | if (isNewArchitectureEnabled() && getReactNativeMinorVersion() < 71) { 117 | implementation project(":ReactAndroid") 118 | } else { 119 | implementation 'com.facebook.react:react-native:+' 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | ReactNativePicker_compileSdkVersion=28 2 | ReactNativePicker_buildToolsVersion=28.0.3 3 | ReactNativePicker_targetSdkVersion=28 4 | ReactNativePicker_minSdkVersion=21 5 | ReactNativePicker_vector_drawable_use_support_library=true 6 | -------------------------------------------------------------------------------- /android/src/fabric/java/com/reactnativecommunity/picker/FabricEnabledPicker.java: -------------------------------------------------------------------------------- 1 | package com.reactnativecommunity.picker; 2 | 3 | import android.content.Context; 4 | import android.content.res.Resources; 5 | import android.util.AttributeSet; 6 | 7 | import androidx.annotation.NonNull; 8 | import androidx.annotation.Nullable; 9 | import androidx.annotation.UiThread; 10 | import androidx.appcompat.widget.AppCompatSpinner; 11 | 12 | import com.facebook.react.bridge.ReadableMap; 13 | import com.facebook.react.bridge.WritableMap; 14 | import com.facebook.react.bridge.WritableNativeMap; 15 | import com.facebook.react.uimanager.PixelUtil; 16 | import com.facebook.react.uimanager.StateWrapper; 17 | 18 | public abstract class FabricEnabledPicker extends AppCompatSpinner { 19 | private StateWrapper mStateWrapper = null; 20 | 21 | @Nullable 22 | public StateWrapper getStateWrapper() { 23 | return mStateWrapper; 24 | } 25 | 26 | public void setStateWrapper(StateWrapper stateWrapper) { 27 | mStateWrapper = stateWrapper; 28 | } 29 | 30 | protected void setMeasuredHeight(int height) { 31 | updateState(height); 32 | } 33 | 34 | @UiThread 35 | void updateState(int measuredHeight) { 36 | float realHeight = PixelUtil.toDIPFromPixel(measuredHeight); 37 | 38 | // Check incoming state values. If they're already the correct value, return early to prevent 39 | // infinite UpdateState/SetState loop. 40 | ReadableMap currentState = mStateWrapper.getStateData(); 41 | if (currentState != null) { 42 | float stateHeight = currentState.hasKey("measuredHeight") ? currentState.getInt("measuredHeight") : 1; 43 | if (Math.abs(stateHeight - realHeight) < 0.9) { 44 | return; 45 | } 46 | } 47 | WritableMap map = new WritableNativeMap(); 48 | map.putDouble("measuredHeight", realHeight); 49 | mStateWrapper.updateState(map); 50 | } 51 | 52 | public FabricEnabledPicker(@NonNull Context context) { 53 | super(context); 54 | } 55 | 56 | public FabricEnabledPicker(@NonNull Context context, int mode) { 57 | super(context, mode); 58 | } 59 | 60 | public FabricEnabledPicker(@NonNull Context context, @Nullable AttributeSet attrs) { 61 | super(context, attrs); 62 | } 63 | 64 | public FabricEnabledPicker(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 65 | super(context, attrs, defStyleAttr); 66 | } 67 | 68 | public FabricEnabledPicker(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int mode) { 69 | super(context, attrs, defStyleAttr, mode); 70 | } 71 | 72 | public FabricEnabledPicker(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int mode, Resources.Theme popupTheme) { 73 | super(context, attrs, defStyleAttr, mode, popupTheme); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /android/src/main/java/com/reactnativecommunity/picker/CheckedTextViewImpl.java: -------------------------------------------------------------------------------- 1 | package com.reactnativecommunity.picker; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.widget.CheckedTextView; 6 | 7 | import androidx.appcompat.widget.AppCompatCheckedTextView; 8 | 9 | public class CheckedTextViewImpl extends AppCompatCheckedTextView { 10 | public CheckedTextViewImpl(Context context) { 11 | super(context); 12 | } 13 | 14 | public CheckedTextViewImpl(Context context, AttributeSet attrs) { 15 | super(context, attrs); 16 | } 17 | 18 | public CheckedTextViewImpl(Context context, AttributeSet attrs, int defStyleAttr) { 19 | super(context, attrs, defStyleAttr); 20 | } 21 | 22 | @Override 23 | public void setHorizontallyScrolling(boolean whether) { 24 | // scrolling breaks multiline texts 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /android/src/main/java/com/reactnativecommunity/picker/PickerBlurEvent.java: -------------------------------------------------------------------------------- 1 | package com.reactnativecommunity.picker; 2 | 3 | import com.facebook.react.bridge.Arguments; 4 | import com.facebook.react.bridge.WritableMap; 5 | import com.facebook.react.uimanager.events.Event; 6 | import com.facebook.react.uimanager.events.RCTEventEmitter; 7 | 8 | public class PickerBlurEvent extends Event { 9 | public static final String EVENT_NAME = "topBlur"; 10 | @Override 11 | public String getEventName() { 12 | return EVENT_NAME; 13 | } 14 | 15 | public PickerBlurEvent(int id) { 16 | super(id); 17 | } 18 | 19 | @Override 20 | public void dispatch(RCTEventEmitter rctEventEmitter) { 21 | rctEventEmitter.receiveEvent(getViewTag(), getEventName(), getEventData()); 22 | } 23 | 24 | /** 25 | * In RN version 0.65+ getEventData method is introduced 26 | * https://github.com/facebook/react-native/commit/72d0ddc16f2f631003c3486e0a59e50c145ec613 27 | * 28 | * In order to keep compatibility with 0.65+ and not introduce breaking change for that lib, 29 | * the only change is changing access modifier from `private` to `protected` without using @override annotation 30 | * (idk if it will not bring any "method is hidden, but should overriden" warning, but for now it just works) 31 | * 32 | * In future versions, where `dispatch` method will be removed, there will be need to make a breaking change here 33 | */ 34 | protected WritableMap getEventData() { 35 | WritableMap eventData = Arguments.createMap(); 36 | eventData.putInt("target", getViewTag()); 37 | return eventData; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /android/src/main/java/com/reactnativecommunity/picker/PickerFocusEvent.java: -------------------------------------------------------------------------------- 1 | package com.reactnativecommunity.picker; 2 | 3 | import com.facebook.react.bridge.Arguments; 4 | import com.facebook.react.bridge.WritableMap; 5 | import com.facebook.react.uimanager.events.Event; 6 | import com.facebook.react.uimanager.events.RCTEventEmitter; 7 | 8 | public class PickerFocusEvent extends Event { 9 | public static final String EVENT_NAME = "topFocus"; 10 | @Override 11 | public String getEventName() { 12 | return EVENT_NAME; 13 | } 14 | 15 | public PickerFocusEvent(int id) { 16 | super(id); 17 | } 18 | 19 | @Override 20 | public void dispatch(RCTEventEmitter rctEventEmitter) { 21 | rctEventEmitter.receiveEvent(getViewTag(), getEventName(), getEventData()); 22 | } 23 | 24 | /** 25 | * In RN version 0.65+ getEventData method is introduced 26 | * https://github.com/facebook/react-native/commit/72d0ddc16f2f631003c3486e0a59e50c145ec613 27 | * 28 | * In order to keep compatibility with 0.65+ and not introduce breaking change for that lib, 29 | * the only change is changing access modifier from `private` to `protected` without using @override annotation 30 | * (idk if it will not bring any "method is hidden, but should overriden" warning, but for now it just works) 31 | * 32 | * In future versions, where `dispatch` method will be removed, there will be need to make a breaking change here 33 | */ 34 | protected WritableMap getEventData() { 35 | WritableMap eventData = Arguments.createMap(); 36 | eventData.putInt("target", getViewTag()); 37 | return eventData; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /android/src/main/java/com/reactnativecommunity/picker/PickerItemSelectEvent.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | package com.reactnativecommunity.picker; 9 | 10 | import com.facebook.react.bridge.Arguments; 11 | import com.facebook.react.bridge.WritableMap; 12 | import com.facebook.react.uimanager.events.Event; 13 | import com.facebook.react.uimanager.events.RCTEventEmitter; 14 | 15 | public class PickerItemSelectEvent extends Event { 16 | public static final String EVENT_NAME = "topSelect"; 17 | 18 | private final int mPosition; 19 | 20 | public PickerItemSelectEvent(int id, int position) { 21 | super(id); 22 | mPosition = position; 23 | } 24 | 25 | @Override 26 | public String getEventName() { 27 | return EVENT_NAME; 28 | } 29 | 30 | @Override 31 | public void dispatch(RCTEventEmitter rctEventEmitter) { 32 | rctEventEmitter.receiveEvent(getViewTag(), getEventName(), serializeEventData()); 33 | } 34 | 35 | private WritableMap serializeEventData() { 36 | WritableMap eventData = Arguments.createMap(); 37 | eventData.putInt("position", mPosition); 38 | return eventData; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /android/src/main/java/com/reactnativecommunity/picker/RNCPickerPackage.java: -------------------------------------------------------------------------------- 1 | 2 | package com.reactnativecommunity.picker; 3 | 4 | import androidx.annotation.NonNull; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Collections; 8 | import java.util.List; 9 | 10 | import com.facebook.react.ReactPackage; 11 | import com.facebook.react.bridge.NativeModule; 12 | import com.facebook.react.bridge.ReactApplicationContext; 13 | import com.facebook.react.uimanager.ViewManager; 14 | 15 | public class RNCPickerPackage implements ReactPackage { 16 | @NonNull 17 | @Override 18 | public List createNativeModules(@NonNull ReactApplicationContext reactContext) { 19 | return Collections.emptyList(); 20 | } 21 | 22 | @NonNull 23 | @Override 24 | public List createViewManagers(@NonNull ReactApplicationContext reactContext) { 25 | List list = new ArrayList<>(); 26 | list.add(new ReactDialogPickerManager()); 27 | list.add(new ReactDropdownPickerManager()); 28 | return list; 29 | } 30 | } -------------------------------------------------------------------------------- /android/src/main/java/com/reactnativecommunity/picker/ReactDialogPickerManager.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | package com.reactnativecommunity.picker; 9 | 10 | import android.widget.Spinner; 11 | 12 | import androidx.annotation.NonNull; 13 | import androidx.annotation.Nullable; 14 | 15 | import com.facebook.react.module.annotations.ReactModule; 16 | import com.facebook.react.uimanager.ThemedReactContext; 17 | import com.facebook.react.uimanager.ViewManagerDelegate; 18 | import com.facebook.react.viewmanagers.RNCAndroidDialogPickerManagerDelegate; 19 | import com.facebook.react.viewmanagers.RNCAndroidDialogPickerManagerInterface; 20 | 21 | /** 22 | * {@link ReactPickerManager} for {@link ReactPicker} with {@link Spinner#MODE_DIALOG}. 23 | */ 24 | @ReactModule(name = ReactDialogPickerManager.REACT_CLASS) 25 | public class ReactDialogPickerManager extends ReactPickerManager implements RNCAndroidDialogPickerManagerInterface { 26 | public static final String REACT_CLASS = "RNCAndroidDialogPicker"; 27 | private final ViewManagerDelegate mDelegate = new RNCAndroidDialogPickerManagerDelegate<>(this); 28 | 29 | @Nullable 30 | @Override 31 | protected ViewManagerDelegate getDelegate() { 32 | return mDelegate; 33 | } 34 | 35 | public ReactDialogPickerManager() { 36 | } 37 | 38 | @NonNull 39 | @Override 40 | public String getName() { 41 | return REACT_CLASS; 42 | } 43 | 44 | @NonNull 45 | @Override 46 | protected ReactPicker createViewInstance(@NonNull ThemedReactContext reactContext) { 47 | return new ReactPicker(reactContext, Spinner.MODE_DIALOG); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /android/src/main/java/com/reactnativecommunity/picker/ReactDropdownPickerManager.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | package com.reactnativecommunity.picker; 9 | 10 | import android.widget.Spinner; 11 | 12 | import androidx.annotation.NonNull; 13 | import androidx.annotation.Nullable; 14 | 15 | import com.facebook.react.module.annotations.ReactModule; 16 | import com.facebook.react.uimanager.ThemedReactContext; 17 | import com.facebook.react.uimanager.ViewManagerDelegate; 18 | import com.facebook.react.viewmanagers.RNCAndroidDropdownPickerManagerDelegate; 19 | import com.facebook.react.viewmanagers.RNCAndroidDropdownPickerManagerInterface; 20 | 21 | /** 22 | * {@link ReactPickerManager} for {@link ReactPicker} with {@link Spinner#MODE_DROPDOWN}. 23 | */ 24 | @ReactModule(name = ReactDropdownPickerManager.REACT_CLASS) 25 | public class ReactDropdownPickerManager extends ReactPickerManager implements RNCAndroidDropdownPickerManagerInterface { 26 | 27 | public static final String REACT_CLASS = "RNCAndroidDropdownPicker"; 28 | private final ViewManagerDelegate mDelegate = new RNCAndroidDropdownPickerManagerDelegate<>(this); 29 | 30 | @Nullable 31 | @Override 32 | protected ViewManagerDelegate getDelegate() { 33 | return mDelegate; 34 | } 35 | 36 | public ReactDropdownPickerManager() { 37 | } 38 | 39 | @NonNull 40 | @Override 41 | public String getName() { 42 | return REACT_CLASS; 43 | } 44 | 45 | @NonNull 46 | @Override 47 | protected ReactPicker createViewInstance(@NonNull ThemedReactContext reactContext) { 48 | return new ReactPicker(reactContext, Spinner.MODE_DROPDOWN); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /android/src/main/java/com/reactnativecommunity/picker/ReactPickerLocalData.java: -------------------------------------------------------------------------------- 1 | package com.reactnativecommunity.picker; 2 | 3 | public class ReactPickerLocalData { 4 | private final int height; 5 | 6 | public ReactPickerLocalData(int height) { 7 | this.height = height; 8 | } 9 | 10 | public int getHeight() { 11 | return height; 12 | } 13 | 14 | @Override 15 | public boolean equals(Object o) { 16 | if (this == o) return true; 17 | if (o == null || getClass() != o.getClass()) return false; 18 | ReactPickerLocalData that = (ReactPickerLocalData) o; 19 | return height == that.height; 20 | } 21 | 22 | @Override 23 | public int hashCode() { 24 | return 31 + height; 25 | } 26 | 27 | @Override 28 | public String toString() { 29 | return "RectPickerLocalData{" + 30 | "height=" + height + 31 | '}'; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /android/src/main/java/com/reactnativecommunity/picker/ReactPickerShadowNode.java: -------------------------------------------------------------------------------- 1 | package com.reactnativecommunity.picker; 2 | 3 | import com.facebook.infer.annotation.Assertions; 4 | import com.facebook.react.uimanager.LayoutShadowNode; 5 | 6 | public class ReactPickerShadowNode extends LayoutShadowNode { 7 | @Override 8 | public void setLocalData(Object data) { 9 | Assertions.assertCondition(data instanceof ReactPickerLocalData); 10 | setStyleMinHeight(((ReactPickerLocalData) data).getHeight()); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /android/src/main/java/com/reactnativecommunity/picker/TextViewImpl.java: -------------------------------------------------------------------------------- 1 | package com.reactnativecommunity.picker; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.widget.TextView; 6 | 7 | import androidx.appcompat.widget.AppCompatTextView; 8 | 9 | public class TextViewImpl extends AppCompatTextView { 10 | public TextViewImpl(Context context) { 11 | super(context); 12 | } 13 | 14 | public TextViewImpl(Context context, AttributeSet attrs) { 15 | super(context, attrs); 16 | } 17 | 18 | public TextViewImpl(Context context, AttributeSet attrs, int defStyleAttr) { 19 | super(context, attrs, defStyleAttr); 20 | } 21 | 22 | @Override 23 | public void setHorizontallyScrolling(boolean whether) { 24 | // scrolling breaks multiline texts 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /android/src/main/jni/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | set(CMAKE_VERBOSE_MAKEFILE ON) 3 | 4 | set(LIB_LITERAL rnpicker) 5 | set(LIB_TARGET_NAME react_codegen_${LIB_LITERAL}) 6 | 7 | set(LIB_ANDROID_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..) 8 | set(LIB_ANDROID_GENERATED_JNI_DIR ${LIB_ANDROID_DIR}/build/generated/source/codegen/jni) 9 | set(LIB_ANDROID_GENERATED_COMPONENTS_DIR ${LIB_ANDROID_GENERATED_JNI_DIR}/react/renderer/components/${LIB_LITERAL}) 10 | 11 | add_compile_options( 12 | -fexceptions 13 | -frtti 14 | -std=c++20 15 | -Wall 16 | -Wpedantic 17 | -Wno-gnu-zero-variadic-macro-arguments 18 | ) 19 | 20 | file(GLOB LIB_CUSTOM_SRCS CONFIGURE_DEPENDS *.cpp) 21 | file(GLOB LIB_CODEGEN_SRCS CONFIGURE_DEPENDS ${LIB_ANDROID_GENERATED_COMPONENTS_DIR}/*.cpp) 22 | 23 | add_library( 24 | ${LIB_TARGET_NAME} 25 | SHARED 26 | ${LIB_CUSTOM_SRCS} 27 | ${LIB_CODEGEN_SRCS} 28 | ) 29 | 30 | target_include_directories( 31 | ${LIB_TARGET_NAME} 32 | PUBLIC 33 | . 34 | ${LIB_ANDROID_GENERATED_JNI_DIR} 35 | ${LIB_ANDROID_GENERATED_COMPONENTS_DIR} 36 | ) 37 | 38 | if(ReactAndroid_VERSION_MINOR GREATER_EQUAL 76) 39 | target_link_libraries( 40 | ${LIB_TARGET_NAME} 41 | ReactAndroid::reactnative 42 | ReactAndroid::jsi 43 | fbjni::fbjni 44 | ) 45 | else() 46 | target_link_libraries( 47 | ${LIB_TARGET_NAME} 48 | fbjni 49 | folly_runtime 50 | glog 51 | jsi 52 | react_codegen_rncore 53 | react_debug 54 | react_nativemodule_core 55 | react_render_componentregistry 56 | react_utils 57 | react_render_core 58 | react_render_debug 59 | react_render_graphics 60 | react_render_mapbuffer 61 | rrc_view 62 | turbomodulejsijni 63 | yoga 64 | ) 65 | endif() 66 | 67 | target_compile_options( 68 | ${LIB_TARGET_NAME} 69 | PRIVATE 70 | -DLOG_TAG=\"ReactNative\" 71 | -fexceptions 72 | -frtti 73 | -std=c++20 74 | -Wall 75 | ) 76 | 77 | target_include_directories( 78 | ${CMAKE_PROJECT_NAME} 79 | PUBLIC 80 | ${CMAKE_CURRENT_SOURCE_DIR} 81 | ) 82 | -------------------------------------------------------------------------------- /android/src/main/jni/RNCAndroidDialogPickerMeasurementsManager.cpp: -------------------------------------------------------------------------------- 1 | #include "RNCAndroidDialogPickerMeasurementsManager.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace facebook::jni; 9 | 10 | namespace facebook::react { 11 | // Based on 12 | // react-native/ReactCommon/react/renderer/components/switch/androidswitch/react/renderer/components/androidswitch/AndroidSwitchMeasurementsManager.cpp 13 | // This class is shared between the shadow nodes and allows us to measure the 14 | // progress bar. It calls the measure method of the 15 | // ReactProgressBarViewManager.java which is responsible for the actual 16 | // measurement of the progress bar. 17 | Size RNCAndroidDialogPickerMeasurementsManager::measure( 18 | SurfaceId surfaceId, 19 | LayoutConstraints layoutConstraints, 20 | const RNCAndroidDialogPickerProps& props, 21 | RNCAndroidDialogPickerState state) const { 22 | if (state.measuredHeight > 0) { 23 | return Size{0, state.measuredHeight}; 24 | } 25 | 26 | const jni::global_ref& fabricUIManager = 27 | contextContainer_->at>("FabricUIManager"); 28 | 29 | static auto measure = 30 | jni::findClassStatic("com/facebook/react/fabric/FabricUIManager") 31 | ->getMethod("measure"); 41 | 42 | auto minimumSize = layoutConstraints.minimumSize; 43 | auto maximumSize = layoutConstraints.maximumSize; 44 | 45 | local_ref componentName = make_jstring("RNCAndroidDialogPicker"); 46 | 47 | // override selected index with selectedIndex from state if set 48 | folly::dynamic serializedProps = dialogToDynamic(props); 49 | 50 | local_ref propsRNM = 51 | ReadableNativeMap::newObjectCxxArgs(serializedProps); 52 | local_ref propsRM = 53 | make_local(reinterpret_cast(propsRNM.get())); 54 | 55 | auto measurement = yogaMeassureToSize(measure( 56 | fabricUIManager, 57 | surfaceId, 58 | componentName.get(), 59 | nullptr, 60 | propsRM.get(), 61 | nullptr, 62 | minimumSize.width, 63 | maximumSize.width, 64 | minimumSize.height, 65 | maximumSize.height)); 66 | 67 | return measurement; 68 | } 69 | 70 | } // namespace facebook::react 71 | -------------------------------------------------------------------------------- /android/src/main/jni/RNCAndroidDialogPickerMeasurementsManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "RNCAndroidDialogPickerState.h" 8 | #include "conversions.h" 9 | 10 | namespace facebook::react { 11 | 12 | class RNCAndroidDialogPickerMeasurementsManager { 13 | public: 14 | RNCAndroidDialogPickerMeasurementsManager( 15 | const ContextContainer::Shared& contextContainer) 16 | : contextContainer_(contextContainer) {} 17 | 18 | Size measure( 19 | SurfaceId surfaceId, 20 | LayoutConstraints layoutConstraints, 21 | const RNCAndroidDialogPickerProps& props, 22 | RNCAndroidDialogPickerState state) const; 23 | 24 | private: 25 | const ContextContainer::Shared contextContainer_; 26 | }; 27 | } // namespace facebook::react 28 | -------------------------------------------------------------------------------- /android/src/main/jni/RNCAndroidDialogPickerShadowNode.cpp: -------------------------------------------------------------------------------- 1 | #include "RNCAndroidDialogPickerShadowNode.h" 2 | 3 | #include 4 | 5 | namespace facebook::react { 6 | 7 | extern const char RNCAndroidDialogPickerComponentName[] = 8 | "RNCAndroidDialogPicker"; 9 | 10 | void RNCAndroidDialogPickerShadowNode::setDialogPickerMeasurementsManager( 11 | const std::shared_ptr& 12 | measurementsManager) { 13 | ensureUnsealed(); 14 | measurementsManager_ = measurementsManager; 15 | } 16 | 17 | #pragma mark - LayoutableShadowNode 18 | 19 | Size RNCAndroidDialogPickerShadowNode::measureContent( 20 | LayoutContext const& layoutContext, 21 | LayoutConstraints const& layoutConstraints) const { 22 | return measurementsManager_->measure( 23 | getSurfaceId(), layoutConstraints, getConcreteProps(), getStateData()); 24 | } 25 | 26 | } // namespace facebook::react 27 | -------------------------------------------------------------------------------- /android/src/main/jni/RNCAndroidDialogPickerShadowNode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "RNCAndroidDialogPickerMeasurementsManager.h" 4 | #include "RNCAndroidDialogPickerState.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | namespace facebook::react { 11 | 12 | extern const char RNCAndroidDialogPickerComponentName[]; 13 | 14 | class RNCAndroidDialogPickerShadowNode final 15 | : public ConcreteViewShadowNode< 16 | RNCAndroidDialogPickerComponentName, 17 | RNCAndroidDialogPickerProps, 18 | RNCAndroidDialogPickerEventEmitter, 19 | RNCAndroidDialogPickerState> { 20 | public: 21 | using ConcreteViewShadowNode::ConcreteViewShadowNode; 22 | // Associates a shared `RNCAndroidDialogPickerMeasurementsManager` with the 23 | // node. 24 | void setDialogPickerMeasurementsManager( 25 | const std::shared_ptr& 26 | measurementsManager); 27 | 28 | #pragma mark - LayoutableShadowNode 29 | 30 | Size measureContent( 31 | const LayoutContext& layoutContext, 32 | const LayoutConstraints& layoutConstraints) const override; 33 | 34 | private: 35 | std::shared_ptr 36 | measurementsManager_; 37 | }; 38 | 39 | } // namespace facebook::react 40 | -------------------------------------------------------------------------------- /android/src/main/jni/RNCAndroidDialogPickerState.cpp: -------------------------------------------------------------------------------- 1 | #include "RNCAndroidDialogPickerState.h" 2 | 3 | namespace facebook::react { 4 | 5 | #ifdef ANDROID 6 | folly::dynamic RNCAndroidDialogPickerState::getDynamic() const { 7 | return folly::dynamic::object("measuredHeight", measuredHeight); 8 | } 9 | #endif 10 | 11 | } // namespace facebook::react 12 | -------------------------------------------------------------------------------- /android/src/main/jni/RNCAndroidDialogPickerState.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #ifdef ANDROID 7 | #include 8 | #include 9 | #include 10 | #endif 11 | 12 | namespace facebook::react { 13 | 14 | class JSI_EXPORT RNCAndroidDialogPickerState final { 15 | public: 16 | using Shared = std::shared_ptr; 17 | 18 | RNCAndroidDialogPickerState() : measuredHeight(-1){}; 19 | RNCAndroidDialogPickerState(int measuredHeight_) 20 | : measuredHeight(measuredHeight_){}; 21 | 22 | #ifdef ANDROID 23 | RNCAndroidDialogPickerState( 24 | RNCAndroidDialogPickerState const& previousState, 25 | folly::dynamic data) 26 | : measuredHeight((Float)data["measuredHeight"].getDouble()){}; 27 | #endif 28 | 29 | const float measuredHeight; 30 | 31 | #ifdef ANDROID 32 | folly::dynamic getDynamic() const; 33 | MapBuffer getMapBuffer() const { 34 | return MapBufferBuilder::EMPTY(); 35 | }; 36 | 37 | #endif 38 | 39 | #pragma mark - Getters 40 | }; 41 | 42 | } // namespace facebook::react 43 | -------------------------------------------------------------------------------- /android/src/main/jni/RNCAndroidDropdownPickerMeasurementsManager.cpp: -------------------------------------------------------------------------------- 1 | #include "RNCAndroidDropdownPickerMeasurementsManager.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace facebook::jni; 9 | 10 | namespace facebook::react { 11 | // Based on 12 | // react-native/ReactCommon/react/renderer/components/switch/androidswitch/react/renderer/components/androidswitch/AndroidSwitchMeasurementsManager.cpp 13 | // This class is shared between the shadow nodes and allows us to measure the 14 | // progress bar. It calls the measure method of the 15 | // ReactProgressBarViewManager.java which is responsible for the actual 16 | // measurement of the progress bar. 17 | Size RNCAndroidDropdownPickerMeasurementsManager::measure( 18 | SurfaceId surfaceId, 19 | LayoutConstraints layoutConstraints, 20 | const RNCAndroidDropdownPickerProps& props, 21 | RNCAndroidDropdownPickerState state) const { 22 | if (state.measuredHeight > 0) { 23 | return Size{0, state.measuredHeight}; 24 | } 25 | 26 | const jni::global_ref& fabricUIManager = 27 | contextContainer_->at>("FabricUIManager"); 28 | 29 | static auto measure = 30 | jni::findClassStatic("com/facebook/react/fabric/FabricUIManager") 31 | ->getMethod("measure"); 41 | 42 | auto minimumSize = layoutConstraints.minimumSize; 43 | auto maximumSize = layoutConstraints.maximumSize; 44 | 45 | local_ref componentName = make_jstring("RNCAndroidDropdownPicker"); 46 | 47 | // override selected index with selectedIndex from state if set 48 | folly::dynamic serializedProps = dropdownToDynamic(props); 49 | 50 | local_ref propsRNM = 51 | ReadableNativeMap::newObjectCxxArgs(serializedProps); 52 | local_ref propsRM = 53 | make_local(reinterpret_cast(propsRNM.get())); 54 | 55 | auto measurement = yogaMeassureToSize(measure( 56 | fabricUIManager, 57 | surfaceId, 58 | componentName.get(), 59 | nullptr, 60 | propsRM.get(), 61 | nullptr, 62 | minimumSize.width, 63 | maximumSize.width, 64 | minimumSize.height, 65 | maximumSize.height)); 66 | 67 | return measurement; 68 | } 69 | 70 | } // namespace facebook::react 71 | -------------------------------------------------------------------------------- /android/src/main/jni/RNCAndroidDropdownPickerMeasurementsManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "RNCAndroidDropdownPickerState.h" 8 | #include "conversions.h" 9 | 10 | namespace facebook::react { 11 | 12 | class RNCAndroidDropdownPickerMeasurementsManager { 13 | public: 14 | RNCAndroidDropdownPickerMeasurementsManager( 15 | const ContextContainer::Shared& contextContainer) 16 | : contextContainer_(contextContainer) {} 17 | 18 | Size measure( 19 | SurfaceId surfaceId, 20 | LayoutConstraints layoutConstraints, 21 | const RNCAndroidDropdownPickerProps& props, 22 | RNCAndroidDropdownPickerState state) const; 23 | 24 | private: 25 | const ContextContainer::Shared contextContainer_; 26 | }; 27 | 28 | } // namespace facebook::react 29 | -------------------------------------------------------------------------------- /android/src/main/jni/RNCAndroidDropdownPickerShadowNode.cpp: -------------------------------------------------------------------------------- 1 | #include "RNCAndroidDropdownPickerShadowNode.h" 2 | 3 | #include 4 | 5 | namespace facebook::react { 6 | 7 | extern const char RNCAndroidDropdownPickerComponentName[] = 8 | "RNCAndroidDropdownPicker"; 9 | 10 | void RNCAndroidDropdownPickerShadowNode::setDropdownPickerMeasurementsManager( 11 | const std::shared_ptr& 12 | measurementsManager) { 13 | ensureUnsealed(); 14 | measurementsManager_ = measurementsManager; 15 | } 16 | 17 | #pragma mark - LayoutableShadowNode 18 | 19 | Size RNCAndroidDropdownPickerShadowNode::measureContent( 20 | LayoutContext const& layoutContext, 21 | LayoutConstraints const& layoutConstraints) const { 22 | return measurementsManager_->measure( 23 | getSurfaceId(), layoutConstraints, getConcreteProps(), getStateData()); 24 | } 25 | 26 | } // namespace facebook::react 27 | -------------------------------------------------------------------------------- /android/src/main/jni/RNCAndroidDropdownPickerShadowNode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include "RNCAndroidDropdownPickerMeasurementsManager.h" 7 | #include "RNCAndroidDropdownPickerState.h" 8 | 9 | namespace facebook::react { 10 | 11 | extern const char RNCAndroidDropdownPickerComponentName[]; 12 | 13 | class RNCAndroidDropdownPickerShadowNode final 14 | : public ConcreteViewShadowNode< 15 | RNCAndroidDropdownPickerComponentName, 16 | RNCAndroidDropdownPickerProps, 17 | RNCAndroidDropdownPickerEventEmitter, 18 | RNCAndroidDropdownPickerState> { 19 | public: 20 | using ConcreteViewShadowNode::ConcreteViewShadowNode; 21 | // Associates a shared `RNCAndroidDropdownPickerMeasurementsManager` with the 22 | // node. 23 | void setDropdownPickerMeasurementsManager( 24 | const std::shared_ptr& 25 | measurementsManager); 26 | 27 | #pragma mark - LayoutableShadowNode 28 | 29 | Size measureContent( 30 | const LayoutContext& layoutContext, 31 | const LayoutConstraints& layoutConstraints) const override; 32 | 33 | private: 34 | std::shared_ptr 35 | measurementsManager_; 36 | }; 37 | 38 | } // namespace facebook::react 39 | -------------------------------------------------------------------------------- /android/src/main/jni/RNCAndroidDropdownPickerState.cpp: -------------------------------------------------------------------------------- 1 | #include "RNCAndroidDropdownPickerState.h" 2 | 3 | namespace facebook::react { 4 | 5 | #ifdef ANDROID 6 | folly::dynamic RNCAndroidDropdownPickerState::getDynamic() const { 7 | return folly::dynamic::object("measuredHeight", measuredHeight); 8 | } 9 | #endif 10 | 11 | } // namespace facebook::react 12 | -------------------------------------------------------------------------------- /android/src/main/jni/RNCAndroidDropdownPickerState.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #ifdef ANDROID 7 | #include 8 | #include 9 | #include 10 | #endif 11 | 12 | namespace facebook::react { 13 | 14 | class JSI_EXPORT RNCAndroidDropdownPickerState final { 15 | public: 16 | using Shared = std::shared_ptr; 17 | 18 | RNCAndroidDropdownPickerState() : measuredHeight(0){}; 19 | RNCAndroidDropdownPickerState(float measuredHeight_) 20 | : measuredHeight(measuredHeight_){}; 21 | 22 | #ifdef ANDROID 23 | RNCAndroidDropdownPickerState( 24 | RNCAndroidDropdownPickerState const& previousState, 25 | folly::dynamic data) 26 | : measuredHeight((Float)data["measuredHeight"].getDouble()){}; 27 | #endif 28 | 29 | const float measuredHeight; 30 | 31 | #ifdef ANDROID 32 | folly::dynamic getDynamic() const; 33 | MapBuffer getMapBuffer() const { 34 | return MapBufferBuilder::EMPTY(); 35 | }; 36 | 37 | #endif 38 | 39 | #pragma mark - Getters 40 | }; 41 | 42 | } // namespace facebook::react 43 | -------------------------------------------------------------------------------- /android/src/main/jni/conversions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace facebook::react { 9 | inline folly::dynamic dialogStyleToDynamic( 10 | const RNCAndroidDialogPickerItemsStyleStruct& style) { 11 | folly::dynamic values = folly::dynamic::object(); 12 | 13 | values["color"] = *style.color; 14 | values["backgroundColor"] = *style.backgroundColor; 15 | values["fontFamily"] = style.fontFamily; 16 | values["fontSize"] = style.fontSize; 17 | 18 | return values; 19 | } 20 | 21 | inline folly::dynamic dialogItemsToDynamic( 22 | const std::vector& items) { 23 | folly::dynamic values = folly::dynamic::array(); 24 | 25 | for (const auto& item : items) { 26 | folly::dynamic itemValues = folly::dynamic::object(); 27 | itemValues["label"] = item.label; 28 | itemValues["value"] = item.value; 29 | itemValues["color"] = *item.color; 30 | itemValues["fontFamily"] = item.fontFamily; 31 | itemValues["enabled"] = item.enabled; 32 | itemValues["style"] = dialogStyleToDynamic(item.style); 33 | values.push_back(itemValues); 34 | } 35 | 36 | return values; 37 | } 38 | 39 | inline folly::dynamic dialogToDynamic( 40 | const RNCAndroidDialogPickerProps& props) { 41 | folly::dynamic values = folly::dynamic::object(); 42 | values["items"] = dialogItemsToDynamic(props.items); 43 | values["color"] = *props.color; // TODO: seems not to be used anywhere 44 | values["prompt"] = props.prompt; 45 | values["selected"] = props.selected; 46 | values["backgroundColor"] = props.backgroundColor; 47 | values["dropdownIconColor"] = props.dropdownIconColor; 48 | values["dropdownIconRippleColor"] = props.dropdownIconRippleColor; 49 | values["numberOfLines"] = props.numberOfLines; 50 | values["mode"] = "dialog"; 51 | 52 | return values; 53 | } 54 | 55 | inline folly::dynamic dropdownStyleToDynamic( 56 | const RNCAndroidDropdownPickerItemsStyleStruct& style) { 57 | folly::dynamic values = folly::dynamic::object(); 58 | 59 | values["color"] = *style.color; 60 | values["backgroundColor"] = *style.backgroundColor; 61 | values["fontFamily"] = style.fontFamily; 62 | values["fontSize"] = style.fontSize; 63 | 64 | return values; 65 | } 66 | 67 | inline folly::dynamic dropdownItemsToDynamic( 68 | const std::vector& items) { 69 | folly::dynamic values = folly::dynamic::array(); 70 | 71 | for (const auto& item : items) { 72 | folly::dynamic itemValues = folly::dynamic::object(); 73 | itemValues["label"] = item.label; 74 | itemValues["value"] = item.value; 75 | itemValues["color"] = *item.color; 76 | itemValues["fontFamily"] = item.fontFamily; 77 | itemValues["enabled"] = item.enabled; 78 | itemValues["style"] = dropdownStyleToDynamic(item.style); 79 | values.push_back(itemValues); 80 | } 81 | 82 | return values; 83 | } 84 | 85 | inline folly::dynamic dropdownToDynamic( 86 | const RNCAndroidDropdownPickerProps& props) { 87 | folly::dynamic values = folly::dynamic::object(); 88 | values["items"] = dropdownItemsToDynamic(props.items); 89 | values["color"] = *props.color; // TODO: seems not to be used anywhere 90 | values["prompt"] = props.prompt; 91 | values["selected"] = props.selected; 92 | values["backgroundColor"] = props.backgroundColor; 93 | values["dropdownIconColor"] = props.dropdownIconColor; 94 | values["dropdownIconRippleColor"] = props.dropdownIconRippleColor; 95 | values["numberOfLines"] = props.numberOfLines; 96 | values["mode"] = "dropdown"; 97 | 98 | return values; 99 | } 100 | } // namespace facebook::react 101 | -------------------------------------------------------------------------------- /android/src/main/jni/react/renderer/components/rnpicker/RNCAndroidDialogPickerComponentDescriptor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "RNCAndroidDialogPickerMeasurementsManager.h" 6 | #include "RNCAndroidDialogPickerShadowNode.h" 7 | 8 | namespace facebook::react { 9 | 10 | class RNCAndroidDialogPickerComponentDescriptor final 11 | : public ConcreteComponentDescriptor { 12 | public: 13 | RNCAndroidDialogPickerComponentDescriptor( 14 | const ComponentDescriptorParameters& parameters) 15 | : ConcreteComponentDescriptor(parameters), 16 | measurementsManager_( 17 | std::make_shared( 18 | contextContainer_)) {} 19 | 20 | void adopt(ShadowNode& shadowNode) const override { 21 | ConcreteComponentDescriptor::adopt(shadowNode); 22 | auto& pickerShadowNode = 23 | static_cast(shadowNode); 24 | 25 | // `RNCAndroidDialogPickerShadowNode` uses 26 | // `RNCAndroidDialogPickerMeasurementsManager` to provide measurements to 27 | // Yoga. 28 | pickerShadowNode.setDialogPickerMeasurementsManager(measurementsManager_); 29 | 30 | // All `RNCAndroidDialogPickerShadowNode`s must have leaf Yoga nodes with 31 | // properly setup measure function. 32 | pickerShadowNode.enableMeasurement(); 33 | pickerShadowNode.dirtyLayout(); 34 | } 35 | 36 | private: 37 | const std::shared_ptr 38 | measurementsManager_; 39 | }; 40 | 41 | } // namespace facebook::react 42 | -------------------------------------------------------------------------------- /android/src/main/jni/react/renderer/components/rnpicker/RNCAndroidDropdownPickerComponentDescriptor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "RNCAndroidDropdownPickerMeasurementsManager.h" 6 | #include "RNCAndroidDropdownPickerShadowNode.h" 7 | 8 | namespace facebook::react { 9 | 10 | class RNCAndroidDropdownPickerComponentDescriptor final 11 | : public ConcreteComponentDescriptor { 12 | public: 13 | RNCAndroidDropdownPickerComponentDescriptor( 14 | const ComponentDescriptorParameters& parameters) 15 | : ConcreteComponentDescriptor(parameters), 16 | measurementsManager_( 17 | std::make_shared( 18 | contextContainer_)) {} 19 | 20 | void adopt(ShadowNode& shadowNode) const override { 21 | ConcreteComponentDescriptor::adopt(shadowNode); 22 | auto& pickerShadowNode = 23 | static_cast(shadowNode); 24 | 25 | // `RNCAndroidDropdownPickerShadowNode` uses 26 | // `RNCAndroidDropdownPickerMeasurementsManager` to provide measurements to 27 | // Yoga. 28 | pickerShadowNode.setDropdownPickerMeasurementsManager(measurementsManager_); 29 | 30 | // All `RNCAndroidDropdownPickerShadowNode`s must have leaf Yoga nodes with 31 | // properly setup measure function. 32 | pickerShadowNode.enableMeasurement(); 33 | pickerShadowNode.dirtyLayout(); 34 | } 35 | 36 | private: 37 | const std::shared_ptr 38 | measurementsManager_; 39 | }; 40 | } // namespace facebook::react 41 | -------------------------------------------------------------------------------- /android/src/main/jni/rnpicker.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). 3 | * @generated by codegen project: GenerateModuleJniCpp.js 4 | */ 5 | #include "rnpicker.h" 6 | 7 | namespace facebook::react { 8 | 9 | std::shared_ptr rnpicker_ModuleProvider( 10 | const std::string& moduleName, 11 | const JavaTurboModule::InitParams& params) { 12 | return nullptr; 13 | } 14 | 15 | } // namespace facebook::react 16 | -------------------------------------------------------------------------------- /android/src/main/jni/rnpicker.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | /** 8 | * Note this imports and that they are not present in autogenerated header file 9 | * under android/build/generated/source/codegen/jni/rnpicker.h 10 | * 11 | * It is added here to make the custom symbols visible in autogenerated file 12 | * with code responsible for registering component descriptor providers. See 13 | * that rncli.cpp, located under 14 | * /android/app/build/generated/rncli/src/main/jni/rncli.cpp, includes 15 | * autogenerated rnpicker.h header by default. We change this behaviour by 16 | * appropriate include path configuration so that this header file gets 17 | * included. 18 | */ 19 | #include 20 | #include 21 | 22 | namespace facebook::react { 23 | 24 | JSI_EXPORT 25 | std::shared_ptr rnpicker_ModuleProvider( 26 | const std::string& moduleName, 27 | const JavaTurboModule::InitParams& params); 28 | 29 | } // namespace facebook::react 30 | -------------------------------------------------------------------------------- /android/src/main/res/drawable/ic_dropdown.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /android/src/main/res/drawable/spinner_dropdown_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /android/src/main/res/layout/simple_spinner_dropdown_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | -------------------------------------------------------------------------------- /android/src/main/res/layout/simple_spinner_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | -------------------------------------------------------------------------------- /android/src/paper/java/com/facebook/react/viewmanagers/RNCAndroidDialogPickerManagerDelegate.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). 3 | * 4 | * Do not edit this file as changes may cause incorrect behavior and will be lost 5 | * once the code is regenerated. 6 | * 7 | * @generated by codegen project: GeneratePropsJavaDelegate.js 8 | */ 9 | 10 | package com.facebook.react.viewmanagers; 11 | 12 | import android.view.View; 13 | import androidx.annotation.Nullable; 14 | import com.facebook.react.bridge.ColorPropConverter; 15 | import com.facebook.react.bridge.ReadableArray; 16 | import com.facebook.react.uimanager.BaseViewManager; 17 | import com.facebook.react.uimanager.LayoutShadowNode; 18 | import com.facebook.react.uimanager.BaseViewManagerDelegate; 19 | 20 | public class RNCAndroidDialogPickerManagerDelegate & RNCAndroidDialogPickerManagerInterface> extends BaseViewManagerDelegate { 21 | public RNCAndroidDialogPickerManagerDelegate(U viewManager) { 22 | super(viewManager); 23 | } 24 | @Override 25 | public void setProperty(T view, String propName, @Nullable Object value) { 26 | switch (propName) { 27 | case "items": 28 | mViewManager.setItems(view, (ReadableArray) value); 29 | break; 30 | case "color": 31 | mViewManager.setColor(view, ColorPropConverter.getColor(value, view.getContext())); 32 | break; 33 | case "prompt": 34 | mViewManager.setPrompt(view, value == null ? null : (String) value); 35 | break; 36 | case "enabled": 37 | mViewManager.setEnabled(view, value == null ? false : (boolean) value); 38 | break; 39 | case "selected": 40 | mViewManager.setSelected(view, value == null ? 0 : ((Double) value).intValue()); 41 | break; 42 | case "backgroundColor": 43 | mViewManager.setBackgroundColor(view, value == null ? 0 : ((Double) value).intValue()); 44 | break; 45 | case "dropdownIconColor": 46 | mViewManager.setDropdownIconColor(view, value == null ? 0 : ((Double) value).intValue()); 47 | break; 48 | case "dropdownIconRippleColor": 49 | mViewManager.setDropdownIconRippleColor(view, value == null ? 0 : ((Double) value).intValue()); 50 | break; 51 | case "numberOfLines": 52 | mViewManager.setNumberOfLines(view, value == null ? 0 : ((Double) value).intValue()); 53 | break; 54 | default: 55 | super.setProperty(view, propName, value); 56 | } 57 | } 58 | 59 | @Override 60 | public void receiveCommand(T view, String commandName, ReadableArray args) { 61 | switch (commandName) { 62 | case "focus": 63 | mViewManager.focus(view); 64 | break; 65 | case "blur": 66 | mViewManager.blur(view); 67 | break; 68 | case "setNativeSelected": 69 | mViewManager.setNativeSelected(view, args.getInt(0)); 70 | break; 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /android/src/paper/java/com/facebook/react/viewmanagers/RNCAndroidDialogPickerManagerInterface.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). 3 | * 4 | * Do not edit this file as changes may cause incorrect behavior and will be lost 5 | * once the code is regenerated. 6 | * 7 | * @generated by codegen project: GeneratePropsJavaInterface.js 8 | */ 9 | 10 | package com.facebook.react.viewmanagers; 11 | 12 | import android.view.View; 13 | import androidx.annotation.Nullable; 14 | import com.facebook.react.bridge.ReadableArray; 15 | 16 | public interface RNCAndroidDialogPickerManagerInterface { 17 | void setItems(T view, @Nullable ReadableArray value); 18 | void setColor(T view, @Nullable Integer value); 19 | void setPrompt(T view, @Nullable String value); 20 | void setEnabled(T view, boolean value); 21 | void setSelected(T view, int value); 22 | void setBackgroundColor(T view, int value); 23 | void setDropdownIconColor(T view, int value); 24 | void setDropdownIconRippleColor(T view, int value); 25 | void setNumberOfLines(T view, int value); 26 | void focus(T view); 27 | void blur(T view); 28 | void setNativeSelected(T view, int selected); 29 | } 30 | -------------------------------------------------------------------------------- /android/src/paper/java/com/facebook/react/viewmanagers/RNCAndroidDropdownPickerManagerDelegate.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). 3 | * 4 | * Do not edit this file as changes may cause incorrect behavior and will be lost 5 | * once the code is regenerated. 6 | * 7 | * @generated by codegen project: GeneratePropsJavaDelegate.js 8 | */ 9 | 10 | package com.facebook.react.viewmanagers; 11 | 12 | import android.view.View; 13 | import androidx.annotation.Nullable; 14 | import com.facebook.react.bridge.ColorPropConverter; 15 | import com.facebook.react.bridge.ReadableArray; 16 | import com.facebook.react.uimanager.BaseViewManager; 17 | import com.facebook.react.uimanager.LayoutShadowNode; 18 | import com.facebook.react.uimanager.BaseViewManagerDelegate; 19 | 20 | public class RNCAndroidDropdownPickerManagerDelegate & RNCAndroidDropdownPickerManagerInterface> extends BaseViewManagerDelegate { 21 | public RNCAndroidDropdownPickerManagerDelegate(U viewManager) { 22 | super(viewManager); 23 | } 24 | @Override 25 | public void setProperty(T view, String propName, @Nullable Object value) { 26 | switch (propName) { 27 | case "items": 28 | mViewManager.setItems(view, (ReadableArray) value); 29 | break; 30 | case "color": 31 | mViewManager.setColor(view, ColorPropConverter.getColor(value, view.getContext())); 32 | break; 33 | case "prompt": 34 | mViewManager.setPrompt(view, value == null ? null : (String) value); 35 | break; 36 | case "enabled": 37 | mViewManager.setEnabled(view, value == null ? false : (boolean) value); 38 | break; 39 | case "selected": 40 | mViewManager.setSelected(view, value == null ? 0 : ((Double) value).intValue()); 41 | break; 42 | case "backgroundColor": 43 | mViewManager.setBackgroundColor(view, value == null ? 0 : ((Double) value).intValue()); 44 | break; 45 | case "dropdownIconColor": 46 | mViewManager.setDropdownIconColor(view, value == null ? 0 : ((Double) value).intValue()); 47 | break; 48 | case "dropdownIconRippleColor": 49 | mViewManager.setDropdownIconRippleColor(view, value == null ? 0 : ((Double) value).intValue()); 50 | break; 51 | case "numberOfLines": 52 | mViewManager.setNumberOfLines(view, value == null ? 0 : ((Double) value).intValue()); 53 | break; 54 | default: 55 | super.setProperty(view, propName, value); 56 | } 57 | } 58 | 59 | @Override 60 | public void receiveCommand(T view, String commandName, ReadableArray args) { 61 | switch (commandName) { 62 | case "focus": 63 | mViewManager.focus(view); 64 | break; 65 | case "blur": 66 | mViewManager.blur(view); 67 | break; 68 | case "setNativeSelected": 69 | mViewManager.setNativeSelected(view, args.getInt(0)); 70 | break; 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /android/src/paper/java/com/facebook/react/viewmanagers/RNCAndroidDropdownPickerManagerInterface.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). 3 | * 4 | * Do not edit this file as changes may cause incorrect behavior and will be lost 5 | * once the code is regenerated. 6 | * 7 | * @generated by codegen project: GeneratePropsJavaInterface.js 8 | */ 9 | 10 | package com.facebook.react.viewmanagers; 11 | 12 | import android.view.View; 13 | import androidx.annotation.Nullable; 14 | import com.facebook.react.bridge.ReadableArray; 15 | 16 | public interface RNCAndroidDropdownPickerManagerInterface { 17 | void setItems(T view, @Nullable ReadableArray value); 18 | void setColor(T view, @Nullable Integer value); 19 | void setPrompt(T view, @Nullable String value); 20 | void setEnabled(T view, boolean value); 21 | void setSelected(T view, int value); 22 | void setBackgroundColor(T view, int value); 23 | void setDropdownIconColor(T view, int value); 24 | void setDropdownIconRippleColor(T view, int value); 25 | void setNumberOfLines(T view, int value); 26 | void focus(T view); 27 | void blur(T view); 28 | void setNativeSelected(T view, int selected); 29 | } 30 | -------------------------------------------------------------------------------- /android/src/paper/java/com/reactnativecommunity/picker/FabricEnabledPicker.java: -------------------------------------------------------------------------------- 1 | package com.reactnativecommunity.picker; 2 | 3 | import android.content.Context; 4 | import android.content.res.Resources; 5 | import android.util.AttributeSet; 6 | 7 | import androidx.annotation.NonNull; 8 | import androidx.annotation.Nullable; 9 | import androidx.appcompat.widget.AppCompatSpinner; 10 | 11 | import com.facebook.react.uimanager.StateWrapper; 12 | 13 | public abstract class FabricEnabledPicker extends AppCompatSpinner { 14 | public void setStateWrapper(StateWrapper stateWrapper) { 15 | // NO-OP on paper 16 | } 17 | 18 | protected void setMeasuredHeight(int height) { 19 | // NO-OP on paper 20 | } 21 | 22 | public FabricEnabledPicker(@NonNull Context context) { 23 | super(context); 24 | } 25 | 26 | public FabricEnabledPicker(@NonNull Context context, int mode) { 27 | super(context, mode); 28 | } 29 | 30 | public FabricEnabledPicker(@NonNull Context context, @Nullable AttributeSet attrs) { 31 | super(context, attrs); 32 | } 33 | 34 | public FabricEnabledPicker(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 35 | super(context, attrs, defStyleAttr); 36 | } 37 | 38 | public FabricEnabledPicker(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int mode) { 39 | super(context, attrs, defStyleAttr, mode); 40 | } 41 | 42 | public FabricEnabledPicker(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int mode, Resources.Theme popupTheme) { 43 | super(context, attrs, defStyleAttr, mode, popupTheme); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | entryPoint: './example/App', 3 | }; 4 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:metro-react-native-babel-preset'], 3 | plugins: [ 4 | [ 5 | 'module-resolver', 6 | { 7 | alias: { 8 | '@react-native-picker/picker': './js', 9 | }, 10 | cwd: 'babelrc', 11 | }, 12 | ], 13 | ], 14 | }; 15 | -------------------------------------------------------------------------------- /e2e/PickerAndroidTestModule.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const BatchedBridge = require('./node_modules/BatchedBridge'); 13 | const React = require('React'); 14 | const RecordingModule = require('./node_modules/NativeModules') 15 | .PickerAndroidRecordingModule; 16 | const Picker = require('./node_modules/Picker'); 17 | const View = require('./node_modules/View'); 18 | 19 | const Item = Picker.Item; 20 | 21 | let appInstance; 22 | 23 | class PickerAndroidTestApp extends React.Component { 24 | state = { 25 | selected: 1, 26 | mode: 'dropdown', 27 | style: {}, 28 | }; 29 | 30 | UNSAFE_componentWillMount() { 31 | appInstance = this; 32 | } 33 | 34 | render() { 35 | return ( 36 | 37 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 59 | 60 | 61 | 62 | 63 | 64 | ); 65 | } 66 | 67 | onValueChange = value => { 68 | this.setState({selected: value}); 69 | RecordingModule.recordSelection(value); 70 | }; 71 | } 72 | 73 | const PickerAndroidTestModule = { 74 | PickerAndroidTestApp: PickerAndroidTestApp, 75 | selectItem: function(value) { 76 | appInstance.setState({selected: value}); 77 | }, 78 | setMode: function(mode) { 79 | appInstance.setState({mode: mode}); 80 | }, 81 | setPrimaryColor: function(color) { 82 | appInstance.setState({style: {color}}); 83 | }, 84 | }; 85 | 86 | BatchedBridge.registerCallableModule( 87 | 'PickerAndroidTestModule', 88 | PickerAndroidTestModule, 89 | ); 90 | 91 | module.exports = PickerAndroidTestModule; 92 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | *.binlog 2 | *.hprof 3 | *.xcworkspace/ 4 | *.zip 5 | .DS_Store 6 | .gradle/ 7 | .idea/ 8 | .vs/ 9 | .xcode.env 10 | Pods/ 11 | build/ 12 | dist/* 13 | !dist/.gitignore 14 | local.properties 15 | msbuild.binlog 16 | node_modules/ 17 | -------------------------------------------------------------------------------- /example/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | apply(from: { 3 | def searchDir = rootDir.toPath() 4 | do { 5 | def p = searchDir.resolve("node_modules/react-native-test-app/android/dependencies.gradle") 6 | if (p.toFile().exists()) { 7 | return p.toRealPath().toString() 8 | } 9 | } while (searchDir = searchDir.getParent()) 10 | throw new GradleException("Could not find `react-native-test-app`"); 11 | }()) 12 | 13 | repositories { 14 | mavenCentral() 15 | google() 16 | } 17 | 18 | dependencies { 19 | getReactNativeDependencies().each { dependency -> 20 | classpath(dependency) 21 | } 22 | } 23 | } 24 | 25 | allprojects { 26 | repositories { 27 | maven { 28 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 29 | url({ 30 | def searchDir = rootDir.toPath() 31 | do { 32 | def p = searchDir.resolve("node_modules/react-native/android") 33 | if (p.toFile().exists()) { 34 | return p.toRealPath().toString() 35 | } 36 | } while (searchDir = searchDir.getParent()) 37 | throw new GradleException("Could not find `react-native`"); 38 | }()) 39 | } 40 | mavenCentral() 41 | google() 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the Gradle Daemon. The setting is 11 | # particularly useful for configuring JVM memory settings for build performance. 12 | # This does not affect the JVM settings for the Gradle client VM. 13 | # The default is `-Xmx512m -XX:MaxMetaspaceSize=256m`. 14 | org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 15 | 16 | # When configured, Gradle will fork up to org.gradle.workers.max JVMs to execute 17 | # projects in parallel. To learn more about parallel task execution, see the 18 | # section on Gradle build performance: 19 | # https://docs.gradle.org/current/userguide/performance.html#parallel_execution. 20 | # Default is `false`. 21 | #org.gradle.parallel=true 22 | 23 | # AndroidX package structure to make it clearer which packages are bundled with the 24 | # Android operating system, and which are packaged with your app's APK 25 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 26 | android.useAndroidX=true 27 | # Automatically convert third-party libraries to use AndroidX 28 | android.enableJetifier=true 29 | # Jetifier randomly fails on these libraries 30 | android.jetifier.ignorelist=hermes-android,react-android 31 | 32 | # Use this property to specify which architecture you want to build. 33 | # You can also override it from the CLI using 34 | # ./gradlew -PreactNativeArchitectures=x86_64 35 | reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 36 | 37 | # Use this property to enable support to the new architecture. 38 | # This will allow you to use TurboModules and the Fabric render in 39 | # your application. You should enable this flag either if you want 40 | # to write custom TurboModules/Fabric components OR use libraries that 41 | # are providing them. 42 | # Note that this is incompatible with web debugging. 43 | #newArchEnabled=true 44 | #bridgelessEnabled=true 45 | 46 | # Uncomment the line below to build React Native from source. 47 | #react.buildFromSource=true 48 | 49 | # Version of Android NDK to build against. 50 | #ANDROID_NDK_VERSION=26.1.10909125 51 | 52 | # Version of Kotlin to build against. 53 | #KOTLIN_VERSION=1.8.22 54 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/react-native-picker/picker/11cade13725af12bb79c55769ca80f0f772dd95e/example/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /example/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | @rem This is normally unused 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem Find java.exe 40 | if defined JAVA_HOME goto findJavaFromJavaHome 41 | 42 | set JAVA_EXE=java.exe 43 | %JAVA_EXE% -version >NUL 2>&1 44 | if %ERRORLEVEL% equ 0 goto execute 45 | 46 | echo. 1>&2 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 48 | echo. 1>&2 49 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 50 | echo location of your Java installation. 1>&2 51 | 52 | goto fail 53 | 54 | :findJavaFromJavaHome 55 | set JAVA_HOME=%JAVA_HOME:"=% 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 57 | 58 | if exist "%JAVA_EXE%" goto execute 59 | 60 | echo. 1>&2 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 62 | echo. 1>&2 63 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 64 | echo location of your Java installation. 1>&2 65 | 66 | goto fail 67 | 68 | :execute 69 | @rem Setup the command line 70 | 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 72 | 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 %* 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if %ERRORLEVEL% equ 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 | set EXIT_CODE=%ERRORLEVEL% 85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 87 | exit /b %EXIT_CODE% 88 | 89 | :mainEnd 90 | if "%OS%"=="Windows_NT" endlocal 91 | 92 | :omega 93 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | mavenCentral() 5 | google() 6 | } 7 | } 8 | 9 | rootProject.name = "Example" 10 | 11 | apply(from: { 12 | def searchDir = rootDir.toPath() 13 | do { 14 | def p = searchDir.resolve("node_modules/react-native-test-app/test-app.gradle") 15 | if (p.toFile().exists()) { 16 | return p.toRealPath().toString() 17 | } 18 | } while (searchDir = searchDir.getParent()) 19 | throw new GradleException("Could not find `react-native-test-app`"); 20 | }()) 21 | applyTestAppSettings(settings) 22 | -------------------------------------------------------------------------------- /example/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Example", 3 | "displayName": "Example", 4 | "components": [ 5 | { 6 | "appKey": "Example", 7 | "displayName": "Example" 8 | } 9 | ], 10 | "resources": { 11 | "android": [ 12 | "dist/res", 13 | "dist/main.android.jsbundle" 14 | ], 15 | "ios": [ 16 | "dist/assets", 17 | "dist/main.ios.jsbundle" 18 | ], 19 | "macos": [ 20 | "dist/assets", 21 | "dist/main.macos.jsbundle" 22 | ], 23 | "visionos": [ 24 | "dist/assets", 25 | "dist/main.visionos.jsbundle" 26 | ], 27 | "windows": [ 28 | "dist/assets", 29 | "dist/main.windows.bundle" 30 | ] 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /example/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:@react-native/babel-preset'], 3 | }; 4 | -------------------------------------------------------------------------------- /example/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import {AppRegistry} from 'react-native'; 6 | import App from './src/App'; 7 | import {name as appName} from './app.json'; 8 | 9 | AppRegistry.registerComponent(appName, () => App); 10 | -------------------------------------------------------------------------------- /example/ios/Podfile: -------------------------------------------------------------------------------- 1 | ws_dir = Pathname.new(__dir__) 2 | ws_dir = ws_dir.parent until 3 | File.exist?("#{ws_dir}/node_modules/react-native-test-app/test_app.rb") || 4 | ws_dir.expand_path.to_s == '/' 5 | require "#{ws_dir}/node_modules/react-native-test-app/test_app.rb" 6 | 7 | workspace 'Example.xcworkspace' 8 | 9 | use_test_app! :hermes_enabled => true 10 | -------------------------------------------------------------------------------- /example/macos/Podfile: -------------------------------------------------------------------------------- 1 | ws_dir = Pathname.new(__dir__) 2 | ws_dir = ws_dir.parent until 3 | File.exist?("#{ws_dir}/node_modules/react-native-test-app/macos/test_app.rb") || 4 | ws_dir.expand_path.to_s == '/' 5 | require "#{ws_dir}/node_modules/react-native-test-app/macos/test_app.rb" 6 | 7 | workspace 'Example.xcworkspace' 8 | 9 | use_test_app! :hermes_enabled => true 10 | -------------------------------------------------------------------------------- /example/metro.config.js: -------------------------------------------------------------------------------- 1 | const {makeMetroConfig} = require('@rnx-kit/metro-config'); 2 | module.exports = makeMetroConfig({ 3 | transformer: { 4 | getTransformOptions: async () => ({ 5 | transform: { 6 | experimentalImportSupport: false, 7 | inlineRequires: false, 8 | }, 9 | }), 10 | }, 11 | }); 12 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Example", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "android": "react-native run-android", 7 | "build:android": "npm run mkdist && react-native bundle --entry-file index.js --platform android --dev true --bundle-output dist/main.android.jsbundle --assets-dest dist/res", 8 | "build:ios": "npm run mkdist && react-native bundle --entry-file index.js --platform ios --dev true --bundle-output dist/main.ios.jsbundle --assets-dest dist", 9 | "build:macos": "npm run mkdist && react-native bundle --entry-file index.js --platform macos --dev true --bundle-output dist/main.macos.jsbundle --assets-dest dist", 10 | "build:windows": "npm run mkdist && react-native bundle --entry-file index.js --platform windows --dev true --bundle-output dist/main.windows.bundle --assets-dest dist", 11 | "ios": "react-native run-ios", 12 | "lint": "eslint .", 13 | "macos": "react-native run-macos --scheme Example", 14 | "mkdist": "node -e \"require('node:fs').mkdirSync('dist', { recursive: true, mode: 0o755 })\"", 15 | "start": "react-native start", 16 | "test": "jest", 17 | "windows": "react-native run-windows" 18 | }, 19 | "dependencies": { 20 | "@react-native-picker/picker": "workspace:^", 21 | "react": "18.3.1", 22 | "react-native": "0.76.3", 23 | "react-native-macos": "^0.75.0", 24 | "react-native-windows": "^0.76.0" 25 | }, 26 | "devDependencies": { 27 | "@babel/core": "^7.25.2", 28 | "@babel/preset-env": "^7.25.3", 29 | "@babel/runtime": "^7.25.0", 30 | "@react-native-community/cli": "15.0.1", 31 | "@react-native-community/cli-platform-android": "15.0.1", 32 | "@react-native-community/cli-platform-ios": "15.0.1", 33 | "@react-native/babel-preset": "0.76.3", 34 | "@react-native/eslint-config": "0.76.3", 35 | "@react-native/metro-config": "0.76.3", 36 | "@react-native/typescript-config": "0.76.3", 37 | "@rnx-kit/metro-config": "^2.0.0", 38 | "@types/react": "^18.2.6", 39 | "@types/react-test-renderer": "^18.0.0", 40 | "babel-jest": "^29.6.3", 41 | "eslint": "^8.19.0", 42 | "jest": "^29.6.3", 43 | "prettier": "2.8.8", 44 | "react-native-test-app": "^4.0.4", 45 | "react-test-renderer": "18.3.1", 46 | "typescript": "5.0.4" 47 | }, 48 | "engines": { 49 | "node": ">=18" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /example/react-native.config.js: -------------------------------------------------------------------------------- 1 | const project = (() => { 2 | try { 3 | const {configureProjects} = require('react-native-test-app'); 4 | return configureProjects({ 5 | android: { 6 | sourceDir: 'android', 7 | }, 8 | ios: { 9 | sourceDir: 'ios', 10 | }, 11 | windows: { 12 | sourceDir: 'windows', 13 | solutionFile: 'windows/Example.sln', 14 | }, 15 | }); 16 | } catch (_) { 17 | return undefined; 18 | } 19 | })(); 20 | 21 | module.exports = { 22 | ...(project ? {project} : undefined), 23 | }; 24 | -------------------------------------------------------------------------------- /example/src/App.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { 3 | Platform, 4 | ScrollView, 5 | StyleSheet, 6 | Text, 7 | View, 8 | SafeAreaView, 9 | I18nManager, 10 | Switch, 11 | } from 'react-native'; 12 | 13 | import * as PickerExamples from './PickerExample'; 14 | import * as PickerIOSExamples from './PickerIOSExample'; 15 | import * as PickerWindowsExamples from './PickerWindowsExamples'; 16 | 17 | export default function App() { 18 | const [isRTL, setIsRTL] = React.useState(I18nManager.isRTL); 19 | React.useEffect(() => { 20 | I18nManager.allowRTL(true); 21 | }, []); 22 | return ( 23 | 24 | 25 | 26 | { 29 | setIsRTL(newValue); 30 | I18nManager.forceRTL(newValue); 31 | }} 32 | /> 33 | {I18nManager.isRTL ? 'RTL' : 'LTR'} 34 | 35 | 36 | Picker Examples 37 | {PickerExamples.examples.map((element) => ( 38 | 39 | {element.title} 40 | {element.render()} 41 | 42 | ))} 43 | {Platform.OS === 'ios' && ( 44 | PickerIOS Examples 45 | )} 46 | {Platform.OS === 'ios' && 47 | PickerIOSExamples.examples.map((element) => ( 48 | 49 | {element.title} 50 | {element.render()} 51 | 52 | ))} 53 | {Platform.OS === 'windows' && ( 54 | PickerWindows Examples 55 | )} 56 | {Platform.OS === 'windows' && 57 | PickerWindowsExamples.examples.map((element) => ( 58 | 59 | {element.title} 60 | {element.render()} 61 | 62 | ))} 63 | 64 | 65 | 66 | ); 67 | } 68 | 69 | const styles = StyleSheet.create({ 70 | main: { 71 | backgroundColor: '#F5FCFF', 72 | }, 73 | container: { 74 | padding: 24, 75 | paddingBottom: 60, 76 | }, 77 | title: { 78 | fontSize: 18, 79 | }, 80 | elementContainer: { 81 | marginTop: 8, 82 | }, 83 | heading: { 84 | fontSize: 22, 85 | color: 'black', 86 | }, 87 | rtlSwitchContainer: { 88 | flexDirection: 'row', 89 | justifyContent: 'space-between', 90 | paddingHorizontal: 40, 91 | paddingTop: 20, 92 | }, 93 | }); 94 | -------------------------------------------------------------------------------- /example/src/PickerWindowsExamples.js: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import {View} from 'react-native'; 3 | import {Picker} from '@react-native-picker/picker'; 4 | 5 | const Item: any = Picker.Item; 6 | 7 | function PlaceholderPickerExample() { 8 | return ( 9 | 10 | 11 | 12 | 13 | 14 | 15 | ); 16 | } 17 | 18 | export const examples = [ 19 | { 20 | title: 'Picker with placeholder', 21 | render: PlaceholderPickerExample, 22 | }, 23 | ]; 24 | -------------------------------------------------------------------------------- /example/src/__tests__/PickerExample.test.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import {BasicPickerExample} from '../PickerExample'; 3 | import {fireEvent, render} from '@testing-library/react-native'; 4 | 5 | describe('PickerExample', () => { 6 | it('should set selectedIndex when item changed', () => { 7 | const renderer = render(); 8 | const picker = renderer.getByTestId('basic-picker'); 9 | 10 | // initial selected-value is `key1` at selectedIndex '1' 11 | expect(picker.props.selectedIndex).toStrictEqual(1); 12 | 13 | // trigger a change to the UI, selecting the first element 14 | fireEvent(picker, 'onValueChange', 'key0'); 15 | expect(picker.props.selectedIndex).toStrictEqual(0); 16 | 17 | // trigger a second change to the UI, selecting the seconed element 18 | fireEvent(picker, 'onValueChange', 'key1'); 19 | expect(picker.props.selectedIndex).toStrictEqual(1); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /example/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@react-native/typescript-config/tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /example/windows/.gitignore: -------------------------------------------------------------------------------- 1 | .vs/ 2 | 3 | # User-specific files 4 | *.suo 5 | *.user 6 | *.sln.docstates 7 | 8 | # Build results 9 | ARM64/ 10 | AppPackages/ 11 | [Bb]in/ 12 | [Dd]ebug/ 13 | [Dd]ebugPublic/ 14 | [Oo]bj/ 15 | [Rr]elease/ 16 | [Rr]eleases/ 17 | bld/ 18 | build/ 19 | x64/ 20 | x86/ 21 | 22 | # NuGet Packages Directory 23 | packages/ 24 | 25 | **/Generated Files/** 26 | *.binlog 27 | *.hprof 28 | *.sln 29 | ExperimentalFeatures.props 30 | NuGet.Config 31 | dist/ 32 | msbuild.binlog 33 | node_modules/ 34 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is an entry point for example app 3 | */ 4 | 5 | import {AppRegistry} from 'react-native'; 6 | import App from './example/src/App'; 7 | import {name as appName} from './example/app.json'; 8 | 9 | AppRegistry.registerComponent(appName, () => App); 10 | -------------------------------------------------------------------------------- /ios/RNCPicker.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #import 9 | 10 | #import 11 | 12 | #import "RNCPickerLabel.h" 13 | 14 | #ifdef RCT_NEW_ARCH_ENABLED 15 | #import "RNCPickerComponentView.h" 16 | #endif 17 | 18 | @interface RNCPicker : UIPickerView 19 | 20 | @property (nonatomic, copy) NSArray *items; 21 | @property (nonatomic, assign) NSInteger selectedIndex; 22 | @property (nonatomic, assign) NSInteger selectionColor; 23 | 24 | @property (nonatomic, strong) UIColor *color; 25 | @property (nonatomic, strong) UIFont *font; 26 | @property (nonatomic, assign) NSTextAlignment textAlign; 27 | 28 | @property (nonatomic, assign) NSInteger numberOfLines; 29 | 30 | @property (nonatomic, copy) RCTBubblingEventBlock onChange; 31 | 32 | #ifdef RCT_NEW_ARCH_ENABLED 33 | - (void)pickerView:(__unused UIPickerView *)pickerView 34 | didSelectRow:(NSInteger)row inComponent:(__unused NSInteger)component 35 | withEventEmitter:(facebook::react::SharedViewEventEmitter)eventEmitter; 36 | #endif 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /ios/RNCPickerComponentView.h: -------------------------------------------------------------------------------- 1 | #ifdef RCT_NEW_ARCH_ENABLED 2 | #import 3 | #import 4 | #import 5 | 6 | NS_ASSUME_NONNULL_BEGIN 7 | 8 | @interface RNCPickerComponentView : RCTViewComponentView 9 | 10 | 11 | @end 12 | 13 | NS_ASSUME_NONNULL_END 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /ios/RNCPickerFabricConversions.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | 5 | // copied from RCTFollyConvert 6 | static id RNCPickerConvertFollyDynamicToId(const folly::dynamic &dyn) 7 | { 8 | // I could imagine an implementation which avoids copies by wrapping the 9 | // dynamic in a derived class of NSDictionary. We can do that if profiling 10 | // implies it will help. 11 | 12 | switch (dyn.type()) { 13 | case folly::dynamic::NULLT: 14 | return nil; 15 | case folly::dynamic::BOOL: 16 | return dyn.getBool() ? @YES : @NO; 17 | case folly::dynamic::INT64: 18 | return @(dyn.getInt()); 19 | case folly::dynamic::DOUBLE: 20 | return @(dyn.getDouble()); 21 | case folly::dynamic::STRING: 22 | return [[NSString alloc] initWithBytes:dyn.c_str() length:dyn.size() encoding:NSUTF8StringEncoding]; 23 | case folly::dynamic::ARRAY: { 24 | NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:dyn.size()]; 25 | for (const auto &elem : dyn) { 26 | id value = RNCPickerConvertFollyDynamicToId(elem); 27 | if (value) { 28 | [array addObject:value]; 29 | } 30 | } 31 | return array; 32 | } 33 | case folly::dynamic::OBJECT: { 34 | NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithCapacity:dyn.size()]; 35 | for (const auto &elem : dyn.items()) { 36 | id key = RNCPickerConvertFollyDynamicToId(elem.first); 37 | id value = RNCPickerConvertFollyDynamicToId(elem.second); 38 | if (key && value) { 39 | dict[key] = value; 40 | } 41 | } 42 | return dict; 43 | } 44 | } 45 | } 46 | 47 | static folly::dynamic RNCPickerRNCPickerConvertIdToFollyDynamic(id json) 48 | { 49 | if (json == nil || json == (id)kCFNull) { 50 | return nullptr; 51 | } else if ([json isKindOfClass:[NSNumber class]]) { 52 | const char *objCType = [json objCType]; 53 | switch (objCType[0]) { 54 | // This is a c++ bool or C99 _Bool. On some platforms, BOOL is a bool. 55 | case _C_BOOL: 56 | return (bool)[json boolValue]; 57 | case _C_CHR: 58 | // On some platforms, objc BOOL is a signed char, but it 59 | // might also be a small number. Use the same hack JSC uses 60 | // to distinguish them: 61 | // https://phabricator.intern.facebook.com/diffusion/FBS/browse/master/fbobjc/xplat/third-party/jsc/safari-600-1-4-17/JavaScriptCore/API/JSValue.mm;b8ee03916489f8b12143cd5c0bca546da5014fc9$901 62 | if ([json isKindOfClass:[@YES class]]) { 63 | return (bool)[json boolValue]; 64 | } else { 65 | return [json longLongValue]; 66 | } 67 | case _C_UCHR: 68 | case _C_SHT: 69 | case _C_USHT: 70 | case _C_INT: 71 | case _C_UINT: 72 | case _C_LNG: 73 | case _C_ULNG: 74 | case _C_LNG_LNG: 75 | case _C_ULNG_LNG: 76 | return [json longLongValue]; 77 | 78 | case _C_FLT: 79 | case _C_DBL: 80 | return [json doubleValue]; 81 | 82 | // default: 83 | // fall through 84 | } 85 | } else if ([json isKindOfClass:[NSString class]]) { 86 | NSData *data = [json dataUsingEncoding:NSUTF8StringEncoding]; 87 | return std::string(reinterpret_cast(data.bytes), data.length); 88 | } else if ([json isKindOfClass:[NSArray class]]) { 89 | folly::dynamic array = folly::dynamic::array; 90 | for (id element in json) { 91 | array.push_back(RNCPickerRNCPickerConvertIdToFollyDynamic(element)); 92 | } 93 | return array; 94 | } else if ([json isKindOfClass:[NSDictionary class]]) { 95 | __block folly::dynamic object = folly::dynamic::object(); 96 | 97 | [json enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *value, __unused BOOL *stop) { 98 | object.insert(RNCPickerRNCPickerConvertIdToFollyDynamic(key), RNCPickerRNCPickerConvertIdToFollyDynamic(value)); 99 | }]; 100 | 101 | return object; 102 | } 103 | 104 | return nil; 105 | } 106 | 107 | -------------------------------------------------------------------------------- /ios/RNCPickerLabel.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface RNCPickerLabel : UILabel 4 | 5 | @property (nonatomic, assign) CGFloat topInset; 6 | @property (nonatomic, assign) CGFloat bottomInset; 7 | @property (nonatomic, assign) CGFloat leftInset; 8 | @property (nonatomic, assign) CGFloat rightInset; 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /ios/RNCPickerLabel.mm: -------------------------------------------------------------------------------- 1 | #import "RNCPickerLabel.h" 2 | 3 | @implementation RNCPickerLabel 4 | 5 | - (instancetype)initWithFrame:(CGRect)frame 6 | { 7 | self = [super initWithFrame:frame]; 8 | if (self) { 9 | self.topInset = 0.0; 10 | self.bottomInset = 0.0; 11 | self.leftInset = 0.0; 12 | self.rightInset = 0.0; 13 | } 14 | return self; 15 | } 16 | 17 | - (void)drawTextInRect:(CGRect)rect 18 | { 19 | UIEdgeInsets insets = UIEdgeInsetsMake(self.topInset, self.leftInset, self.bottomInset, self.rightInset); 20 | [super drawTextInRect:UIEdgeInsetsInsetRect(rect, insets)]; 21 | } 22 | 23 | - (CGSize)intrinsicContentSize 24 | { 25 | CGSize intrinsicSuperViewContentSize = [super intrinsicContentSize]; 26 | intrinsicSuperViewContentSize.height += self.topInset + self.bottomInset; 27 | intrinsicSuperViewContentSize.width += self.leftInset + self.rightInset; 28 | return intrinsicSuperViewContentSize; 29 | } 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /ios/RNCPickerManager.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #import 9 | 10 | @interface RNCPickerManager : RCTViewManager 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /ios/RNCPickerManager.mm: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #import "RNCPickerManager.h" 9 | #import "RNCPicker.h" 10 | 11 | #import 12 | #import 13 | 14 | @implementation RNCPickerManager 15 | 16 | RCT_EXPORT_MODULE() 17 | 18 | - (UIView *)view 19 | { 20 | return [RNCPicker new]; 21 | } 22 | 23 | RCT_EXPORT_VIEW_PROPERTY(items, NSArray) 24 | RCT_EXPORT_VIEW_PROPERTY(selectedIndex, NSInteger) 25 | RCT_EXPORT_VIEW_PROPERTY(selectionColor, NSInteger) 26 | RCT_EXPORT_VIEW_PROPERTY(onChange, RCTBubblingEventBlock) 27 | RCT_EXPORT_VIEW_PROPERTY(color, UIColor) 28 | RCT_EXPORT_VIEW_PROPERTY(textAlign, NSTextAlignment) 29 | RCT_EXPORT_VIEW_PROPERTY(numberOfLines, NSInteger) 30 | RCT_CUSTOM_VIEW_PROPERTY(fontSize, NSNumber, RNCPicker) 31 | { 32 | view.font = [RCTFont updateFont:view.font withSize:json ?: @(defaultView.font.pointSize)]; 33 | } 34 | RCT_CUSTOM_VIEW_PROPERTY(fontWeight, NSString, __unused RNCPicker) 35 | { 36 | view.font = [RCTFont updateFont:view.font withWeight:json]; // defaults to normal 37 | } 38 | RCT_CUSTOM_VIEW_PROPERTY(fontStyle, NSString, __unused RNCPicker) 39 | { 40 | view.font = [RCTFont updateFont:view.font withStyle:json]; // defaults to normal 41 | } 42 | RCT_CUSTOM_VIEW_PROPERTY(fontFamily, NSString, RNCPicker) 43 | { 44 | view.font = [RCTFont updateFont:view.font withFamily:json ?: defaultView.font.familyName]; 45 | } 46 | RCT_CUSTOM_VIEW_PROPERTY(themeVariant, NSString, RNCPicker) 47 | { 48 | if (@available(iOS 13.4, *)) { 49 | if (json) { 50 | if ([json isEqual:@"dark"]) 51 | view.overrideUserInterfaceStyle = UIUserInterfaceStyleDark; 52 | else if ([json isEqual:@"light"]) 53 | view.overrideUserInterfaceStyle = UIUserInterfaceStyleLight; 54 | else 55 | view.overrideUserInterfaceStyle = UIUserInterfaceStyleUnspecified; 56 | } 57 | } 58 | } 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /jest.setup.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | * @flow 9 | */ 10 | /* eslint-env jest */ 11 | 12 | // Reset the mocks before each test 13 | global.beforeEach(() => { 14 | jest.resetAllMocks(); 15 | }); 16 | -------------------------------------------------------------------------------- /js/AndroidDialogPickerNativeComponent.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | * @flow 9 | */ 10 | 11 | 'use strict'; 12 | 13 | import * as React from 'react'; 14 | import type {ColorValue} from 'react-native/Libraries/StyleSheet/StyleSheet'; 15 | import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes'; 16 | import type {HostComponent} from 'react-native/Libraries/Renderer/shims/ReactNativeTypes'; 17 | import type { 18 | BubblingEventHandler, 19 | Int32, 20 | Double, 21 | } from 'react-native/Libraries/Types/CodegenTypes'; 22 | 23 | import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; 24 | import codegenNativeCommands from 'react-native/Libraries/Utilities/codegenNativeCommands'; 25 | 26 | export type PickerAndroidChangeEvent = $ReadOnly<{| 27 | position: Int32, 28 | |}>; 29 | 30 | export type PickerItemStyle = $ReadOnly<{| 31 | backgroundColor?: ?ColorValue, 32 | color?: ?ColorValue, 33 | fontSize?: ?Double, 34 | fontFamily?: ?string, 35 | |}>; 36 | 37 | export type PickerItem = $ReadOnly<{| 38 | label: string, 39 | value: ?string, 40 | color?: ColorValue, 41 | fontFamily: ?string, 42 | enabled?: ?boolean, 43 | style?: ?PickerItemStyle, 44 | |}>; 45 | 46 | type NativeProps = $ReadOnly<{| 47 | ...ViewProps, 48 | items: $ReadOnlyArray, 49 | color?: ColorValue, 50 | prompt?: ?string, 51 | enabled?: ?boolean, 52 | selected: Int32, 53 | backgroundColor?: Int32, 54 | dropdownIconColor?: Int32, 55 | dropdownIconRippleColor?: Int32, 56 | numberOfLines?: ?Int32, 57 | onSelect?: BubblingEventHandler, 58 | onFocus?: BubblingEventHandler, 59 | onBlur?: BubblingEventHandler, 60 | |}>; 61 | 62 | type ComponentType = HostComponent; 63 | 64 | interface NativeCommands { 65 | +focus: (viewRef: React.ElementRef) => void; 66 | +blur: (viewRef: React.ElementRef) => void; 67 | +setNativeSelected: ( 68 | viewRef: React.ElementRef, 69 | selected: Int32, 70 | ) => void; 71 | } 72 | 73 | export const Commands: NativeCommands = codegenNativeCommands({ 74 | supportedCommands: ['focus', 'blur', 'setNativeSelected'], 75 | }); 76 | 77 | export default (codegenNativeComponent('RNCAndroidDialogPicker', { 78 | excludedPlatforms: ['iOS'], 79 | interfaceOnly: true, 80 | }): ComponentType); 81 | -------------------------------------------------------------------------------- /js/AndroidDropdownPickerNativeComponent.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | * @flow 9 | */ 10 | 11 | 'use strict'; 12 | 13 | import * as React from 'react'; 14 | import type {ColorValue} from 'react-native/Libraries/StyleSheet/StyleSheet'; 15 | import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes'; 16 | import type {HostComponent} from 'react-native/Libraries/Renderer/shims/ReactNativeTypes'; 17 | import type { 18 | BubblingEventHandler, 19 | Double, 20 | Int32, 21 | } from 'react-native/Libraries/Types/CodegenTypes'; 22 | 23 | import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; 24 | import codegenNativeCommands from 'react-native/Libraries/Utilities/codegenNativeCommands'; 25 | 26 | export type PickerAndroidChangeEvent = $ReadOnly<{| 27 | position: Int32, 28 | |}>; 29 | 30 | export type PickerItemStyle = $ReadOnly<{| 31 | backgroundColor?: ?ColorValue, 32 | color?: ?ColorValue, 33 | fontSize?: ?Double, 34 | fontFamily?: ?string, 35 | |}>; 36 | 37 | export type PickerItem = $ReadOnly<{| 38 | label: string, 39 | value: ?string, 40 | color?: ColorValue, 41 | fontFamily: ?string, 42 | enabled?: ?boolean, 43 | style?: ?PickerItemStyle, 44 | |}>; 45 | 46 | type NativeProps = $ReadOnly<{| 47 | ...ViewProps, 48 | items: $ReadOnlyArray, 49 | color?: ColorValue, 50 | prompt?: ?string, 51 | enabled?: ?boolean, 52 | selected: Int32, 53 | backgroundColor?: Int32, 54 | dropdownIconColor?: Int32, 55 | dropdownIconRippleColor?: Int32, 56 | numberOfLines?: ?Int32, 57 | onSelect?: BubblingEventHandler, 58 | onFocus?: BubblingEventHandler, 59 | onBlur?: BubblingEventHandler, 60 | |}>; 61 | 62 | type ComponentType = HostComponent; 63 | 64 | interface NativeCommands { 65 | +focus: (viewRef: React.ElementRef) => void; 66 | +blur: (viewRef: React.ElementRef) => void; 67 | +setNativeSelected: ( 68 | viewRef: React.ElementRef, 69 | selected: Int32, 70 | ) => void; 71 | } 72 | 73 | export const Commands: NativeCommands = codegenNativeCommands({ 74 | supportedCommands: ['focus', 'blur', 'setNativeSelected'], 75 | }); 76 | 77 | export default (codegenNativeComponent( 78 | 'RNCAndroidDropdownPicker', 79 | { 80 | excludedPlatforms: ['iOS'], 81 | interfaceOnly: true, 82 | }, 83 | ): ComponentType); 84 | -------------------------------------------------------------------------------- /js/Picker.web.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Nicolas Gallagher. 3 | * 4 | * @flow 5 | * 6 | */ 7 | 8 | import * as React from 'react'; 9 | import {unstable_createElement} from 'react-native-web'; 10 | import {forwardRef} from 'react'; 11 | import type {ViewProps} from 'react-native-web/src/exports/View/types'; 12 | import type {GenericStyleProp} from 'react-native-web/src/types'; 13 | import type {TextStyle} from 'react-native-web/src/exports/Text/types'; 14 | import PickerItem from './PickerItem'; 15 | 16 | type PickerProps = { 17 | ...ViewProps, 18 | children?: typeof PickerItem | Array, 19 | enabled?: boolean, 20 | onValueChange?: (number | string, number) => void, 21 | selectedValue?: number | string, 22 | /** 23 | * dropdownIconColor 24 | * Not used for Web. 25 | */ 26 | dropdownIconColor?: string, 27 | /* compat */ 28 | itemStyle?: GenericStyleProp, 29 | mode?: string, 30 | prompt?: string, 31 | }; 32 | 33 | const Select = forwardRef((props: $FlowFixMe, forwardedRef: $FlowFixMe) => 34 | unstable_createElement('select', { 35 | ...props, 36 | ref: forwardedRef, 37 | }), 38 | ); 39 | 40 | const Picker: React$AbstractComponent = forwardRef< 41 | PickerProps, 42 | $FlowFixMe, 43 | >((props, forwardedRef) => { 44 | const { 45 | enabled, 46 | onValueChange, 47 | selectedValue, 48 | itemStyle, 49 | mode, 50 | prompt, 51 | dropdownIconColor, 52 | ...other 53 | } = props; 54 | 55 | const handleChange = React.useCallback( 56 | (e: Object) => { 57 | const {selectedIndex, value} = e.target; 58 | if (onValueChange) { 59 | onValueChange(value, selectedIndex); 60 | } 61 | }, 62 | [onValueChange], 63 | ); 64 | 65 | return ( 66 | // $FlowFixMe 67 |