react-native-picture-selector 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/README.md +627 -0
  2. package/android/CMakeLists.txt +30 -0
  3. package/android/build.gradle +79 -0
  4. package/android/proguard-rules.pro +21 -0
  5. package/android/src/main/AndroidManifest.xml +39 -0
  6. package/android/src/main/kotlin/com/margelo/pictureselector/GlideEngine.kt +80 -0
  7. package/android/src/main/kotlin/com/margelo/pictureselector/HybridPictureSelector.kt +138 -0
  8. package/android/src/main/kotlin/com/margelo/pictureselector/LubanCompressEngine.kt +58 -0
  9. package/android/src/main/kotlin/com/margelo/pictureselector/MediaAssetMapper.kt +69 -0
  10. package/android/src/main/kotlin/com/margelo/pictureselector/NitroPictureSelectorPackage.kt +52 -0
  11. package/android/src/main/kotlin/com/margelo/pictureselector/PictureSelectorOptionsMapper.kt +105 -0
  12. package/android/src/main/kotlin/com/margelo/pictureselector/UCropEngine.kt +57 -0
  13. package/android/src/main/res/xml/file_paths.xml +8 -0
  14. package/ios/HybridPictureSelector.swift +386 -0
  15. package/ios/NitroPictureSelector.podspec +39 -0
  16. package/lib/commonjs/PictureSelector.js +74 -0
  17. package/lib/commonjs/PictureSelector.js.map +1 -0
  18. package/lib/commonjs/index.js +39 -0
  19. package/lib/commonjs/index.js.map +1 -0
  20. package/lib/commonjs/package.json +1 -0
  21. package/lib/commonjs/specs/PictureSelector.nitro.js +34 -0
  22. package/lib/commonjs/specs/PictureSelector.nitro.js.map +1 -0
  23. package/lib/commonjs/types.js +44 -0
  24. package/lib/commonjs/types.js.map +1 -0
  25. package/lib/commonjs/usePictureSelector.js +122 -0
  26. package/lib/commonjs/usePictureSelector.js.map +1 -0
  27. package/lib/module/PictureSelector.js +71 -0
  28. package/lib/module/PictureSelector.js.map +1 -0
  29. package/lib/module/index.js +6 -0
  30. package/lib/module/index.js.map +1 -0
  31. package/lib/module/package.json +1 -0
  32. package/lib/module/specs/PictureSelector.nitro.js +36 -0
  33. package/lib/module/specs/PictureSelector.nitro.js.map +1 -0
  34. package/lib/module/types.js +29 -0
  35. package/lib/module/types.js.map +1 -0
  36. package/lib/module/usePictureSelector.js +119 -0
  37. package/lib/module/usePictureSelector.js.map +1 -0
  38. package/lib/typescript/PictureSelector.d.ts +23 -0
  39. package/lib/typescript/PictureSelector.d.ts.map +1 -0
  40. package/lib/typescript/index.d.ts +6 -0
  41. package/lib/typescript/index.d.ts.map +1 -0
  42. package/lib/typescript/specs/PictureSelector.nitro.d.ts +96 -0
  43. package/lib/typescript/specs/PictureSelector.nitro.d.ts.map +1 -0
  44. package/lib/typescript/types.d.ts +16 -0
  45. package/lib/typescript/types.d.ts.map +1 -0
  46. package/lib/typescript/usePictureSelector.d.ts +26 -0
  47. package/lib/typescript/usePictureSelector.d.ts.map +1 -0
  48. package/nitro.json +11 -0
  49. package/nitrogen/generated/.gitattributes +1 -0
  50. package/nitrogen/generated/android/NitroPictureSelector+autolinking.cmake +81 -0
  51. package/nitrogen/generated/android/NitroPictureSelector+autolinking.gradle +27 -0
  52. package/nitrogen/generated/android/NitroPictureSelectorOnLoad.cpp +41 -0
  53. package/nitrogen/generated/android/NitroPictureSelectorOnLoad.hpp +34 -0
  54. package/nitrogen/generated/android/c++/JCompressOptions.hpp +69 -0
  55. package/nitrogen/generated/android/c++/JCropOptions.hpp +73 -0
  56. package/nitrogen/generated/android/c++/JHybridHybridPictureSelectorSpec.cpp +125 -0
  57. package/nitrogen/generated/android/c++/JHybridHybridPictureSelectorSpec.hpp +64 -0
  58. package/nitrogen/generated/android/c++/JMediaAsset.hpp +98 -0
  59. package/nitrogen/generated/android/c++/JMediaType.hpp +61 -0
  60. package/nitrogen/generated/android/c++/JPickerTheme.hpp +64 -0
  61. package/nitrogen/generated/android/c++/JPictureSelectorOptions.hpp +121 -0
  62. package/nitrogen/generated/android/kotlin/com/margelo/nitro/com/margelo/pictureselector/CompressOptions.kt +47 -0
  63. package/nitrogen/generated/android/kotlin/com/margelo/nitro/com/margelo/pictureselector/CropOptions.kt +50 -0
  64. package/nitrogen/generated/android/kotlin/com/margelo/nitro/com/margelo/pictureselector/HybridHybridPictureSelectorSpec.kt +59 -0
  65. package/nitrogen/generated/android/kotlin/com/margelo/nitro/com/margelo/pictureselector/MediaAsset.kt +68 -0
  66. package/nitrogen/generated/android/kotlin/com/margelo/nitro/com/margelo/pictureselector/MediaType.kt +24 -0
  67. package/nitrogen/generated/android/kotlin/com/margelo/nitro/com/margelo/pictureselector/NitroPictureSelectorOnLoad.kt +35 -0
  68. package/nitrogen/generated/android/kotlin/com/margelo/nitro/com/margelo/pictureselector/PickerTheme.kt +25 -0
  69. package/nitrogen/generated/android/kotlin/com/margelo/nitro/com/margelo/pictureselector/PictureSelectorOptions.kt +65 -0
  70. package/nitrogen/generated/ios/NitroPictureSelector+autolinking.rb +60 -0
  71. package/nitrogen/generated/ios/NitroPictureSelector-Swift-Cxx-Bridge.cpp +49 -0
  72. package/nitrogen/generated/ios/NitroPictureSelector-Swift-Cxx-Bridge.hpp +270 -0
  73. package/nitrogen/generated/ios/NitroPictureSelector-Swift-Cxx-Umbrella.hpp +65 -0
  74. package/nitrogen/generated/ios/c++/HybridHybridPictureSelectorSpecSwift.cpp +11 -0
  75. package/nitrogen/generated/ios/c++/HybridHybridPictureSelectorSpecSwift.hpp +110 -0
  76. package/nitrogen/generated/ios/swift/CompressOptions.swift +83 -0
  77. package/nitrogen/generated/ios/swift/CropOptions.swift +101 -0
  78. package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +46 -0
  79. package/nitrogen/generated/ios/swift/Func_void_std__vector_MediaAsset_.swift +46 -0
  80. package/nitrogen/generated/ios/swift/HybridHybridPictureSelectorSpec.swift +56 -0
  81. package/nitrogen/generated/ios/swift/HybridHybridPictureSelectorSpec_cxx.swift +176 -0
  82. package/nitrogen/generated/ios/swift/MediaAsset.swift +118 -0
  83. package/nitrogen/generated/ios/swift/MediaType.swift +44 -0
  84. package/nitrogen/generated/ios/swift/PickerTheme.swift +48 -0
  85. package/nitrogen/generated/ios/swift/PictureSelectorOptions.swift +182 -0
  86. package/nitrogen/generated/shared/c++/CompressOptions.hpp +95 -0
  87. package/nitrogen/generated/shared/c++/CropOptions.hpp +99 -0
  88. package/nitrogen/generated/shared/c++/HybridHybridPictureSelectorSpec.cpp +22 -0
  89. package/nitrogen/generated/shared/c++/HybridHybridPictureSelectorSpec.hpp +69 -0
  90. package/nitrogen/generated/shared/c++/MediaAsset.hpp +124 -0
  91. package/nitrogen/generated/shared/c++/MediaType.hpp +80 -0
  92. package/nitrogen/generated/shared/c++/PickerTheme.hpp +84 -0
  93. package/nitrogen/generated/shared/c++/PictureSelectorOptions.hpp +132 -0
  94. package/package.json +76 -0
  95. package/src/PictureSelector.ts +72 -0
  96. package/src/index.ts +16 -0
  97. package/src/specs/PictureSelector.nitro.ts +121 -0
  98. package/src/types.ts +38 -0
  99. package/src/usePictureSelector.ts +102 -0
@@ -0,0 +1,84 @@
1
+ ///
2
+ /// PickerTheme.hpp
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ #pragma once
9
+
10
+ #if __has_include(<NitroModules/NitroHash.hpp>)
11
+ #include <NitroModules/NitroHash.hpp>
12
+ #else
13
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
14
+ #endif
15
+ #if __has_include(<NitroModules/JSIConverter.hpp>)
16
+ #include <NitroModules/JSIConverter.hpp>
17
+ #else
18
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
19
+ #endif
20
+ #if __has_include(<NitroModules/NitroDefines.hpp>)
21
+ #include <NitroModules/NitroDefines.hpp>
22
+ #else
23
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
24
+ #endif
25
+
26
+ namespace margelo::nitro::margelo::pictureselector {
27
+
28
+ /**
29
+ * An enum which can be represented as a JavaScript union (PickerTheme).
30
+ */
31
+ enum class PickerTheme {
32
+ DEFAULT SWIFT_NAME(default) = 0,
33
+ WECHAT SWIFT_NAME(wechat) = 1,
34
+ WHITE SWIFT_NAME(white) = 2,
35
+ DARK SWIFT_NAME(dark) = 3,
36
+ } CLOSED_ENUM;
37
+
38
+ } // namespace margelo::nitro::margelo::pictureselector
39
+
40
+ namespace margelo::nitro {
41
+
42
+ // C++ PickerTheme <> JS PickerTheme (union)
43
+ template <>
44
+ struct JSIConverter<margelo::nitro::margelo::pictureselector::PickerTheme> final {
45
+ static inline margelo::nitro::margelo::pictureselector::PickerTheme fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
46
+ std::string unionValue = JSIConverter<std::string>::fromJSI(runtime, arg);
47
+ switch (hashString(unionValue.c_str(), unionValue.size())) {
48
+ case hashString("default"): return margelo::nitro::margelo::pictureselector::PickerTheme::DEFAULT;
49
+ case hashString("wechat"): return margelo::nitro::margelo::pictureselector::PickerTheme::WECHAT;
50
+ case hashString("white"): return margelo::nitro::margelo::pictureselector::PickerTheme::WHITE;
51
+ case hashString("dark"): return margelo::nitro::margelo::pictureselector::PickerTheme::DARK;
52
+ default: [[unlikely]]
53
+ throw std::invalid_argument("Cannot convert \"" + unionValue + "\" to enum PickerTheme - invalid value!");
54
+ }
55
+ }
56
+ static inline jsi::Value toJSI(jsi::Runtime& runtime, margelo::nitro::margelo::pictureselector::PickerTheme arg) {
57
+ switch (arg) {
58
+ case margelo::nitro::margelo::pictureselector::PickerTheme::DEFAULT: return JSIConverter<std::string>::toJSI(runtime, "default");
59
+ case margelo::nitro::margelo::pictureselector::PickerTheme::WECHAT: return JSIConverter<std::string>::toJSI(runtime, "wechat");
60
+ case margelo::nitro::margelo::pictureselector::PickerTheme::WHITE: return JSIConverter<std::string>::toJSI(runtime, "white");
61
+ case margelo::nitro::margelo::pictureselector::PickerTheme::DARK: return JSIConverter<std::string>::toJSI(runtime, "dark");
62
+ default: [[unlikely]]
63
+ throw std::invalid_argument("Cannot convert PickerTheme to JS - invalid value: "
64
+ + std::to_string(static_cast<int>(arg)) + "!");
65
+ }
66
+ }
67
+ static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
68
+ if (!value.isString()) {
69
+ return false;
70
+ }
71
+ std::string unionValue = JSIConverter<std::string>::fromJSI(runtime, value);
72
+ switch (hashString(unionValue.c_str(), unionValue.size())) {
73
+ case hashString("default"):
74
+ case hashString("wechat"):
75
+ case hashString("white"):
76
+ case hashString("dark"):
77
+ return true;
78
+ default:
79
+ return false;
80
+ }
81
+ }
82
+ };
83
+
84
+ } // namespace margelo::nitro
@@ -0,0 +1,132 @@
1
+ ///
2
+ /// PictureSelectorOptions.hpp
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ #pragma once
9
+
10
+ #if __has_include(<NitroModules/JSIConverter.hpp>)
11
+ #include <NitroModules/JSIConverter.hpp>
12
+ #else
13
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
14
+ #endif
15
+ #if __has_include(<NitroModules/NitroDefines.hpp>)
16
+ #include <NitroModules/NitroDefines.hpp>
17
+ #else
18
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
19
+ #endif
20
+ #if __has_include(<NitroModules/JSIHelpers.hpp>)
21
+ #include <NitroModules/JSIHelpers.hpp>
22
+ #else
23
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
24
+ #endif
25
+ #if __has_include(<NitroModules/PropNameIDCache.hpp>)
26
+ #include <NitroModules/PropNameIDCache.hpp>
27
+ #else
28
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
29
+ #endif
30
+
31
+ // Forward declaration of `MediaType` to properly resolve imports.
32
+ namespace margelo::nitro::margelo::pictureselector { enum class MediaType; }
33
+ // Forward declaration of `CropOptions` to properly resolve imports.
34
+ namespace margelo::nitro::margelo::pictureselector { struct CropOptions; }
35
+ // Forward declaration of `CompressOptions` to properly resolve imports.
36
+ namespace margelo::nitro::margelo::pictureselector { struct CompressOptions; }
37
+ // Forward declaration of `PickerTheme` to properly resolve imports.
38
+ namespace margelo::nitro::margelo::pictureselector { enum class PickerTheme; }
39
+
40
+ #include "MediaType.hpp"
41
+ #include <optional>
42
+ #include "CropOptions.hpp"
43
+ #include "CompressOptions.hpp"
44
+ #include "PickerTheme.hpp"
45
+ #include <string>
46
+ #include <vector>
47
+
48
+ namespace margelo::nitro::margelo::pictureselector {
49
+
50
+ /**
51
+ * A struct which can be represented as a JavaScript object (PictureSelectorOptions).
52
+ */
53
+ struct PictureSelectorOptions final {
54
+ public:
55
+ std::optional<MediaType> mediaType SWIFT_PRIVATE;
56
+ std::optional<double> maxCount SWIFT_PRIVATE;
57
+ std::optional<bool> enableCamera SWIFT_PRIVATE;
58
+ std::optional<CropOptions> crop SWIFT_PRIVATE;
59
+ std::optional<CompressOptions> compress SWIFT_PRIVATE;
60
+ std::optional<double> maxVideoDuration SWIFT_PRIVATE;
61
+ std::optional<double> minVideoDuration SWIFT_PRIVATE;
62
+ std::optional<PickerTheme> theme SWIFT_PRIVATE;
63
+ std::optional<std::string> themeColor SWIFT_PRIVATE;
64
+ std::optional<std::vector<std::string>> selectedAssets SWIFT_PRIVATE;
65
+
66
+ public:
67
+ PictureSelectorOptions() = default;
68
+ explicit PictureSelectorOptions(std::optional<MediaType> mediaType, std::optional<double> maxCount, std::optional<bool> enableCamera, std::optional<CropOptions> crop, std::optional<CompressOptions> compress, std::optional<double> maxVideoDuration, std::optional<double> minVideoDuration, std::optional<PickerTheme> theme, std::optional<std::string> themeColor, std::optional<std::vector<std::string>> selectedAssets): mediaType(mediaType), maxCount(maxCount), enableCamera(enableCamera), crop(crop), compress(compress), maxVideoDuration(maxVideoDuration), minVideoDuration(minVideoDuration), theme(theme), themeColor(themeColor), selectedAssets(selectedAssets) {}
69
+
70
+ public:
71
+ friend bool operator==(const PictureSelectorOptions& lhs, const PictureSelectorOptions& rhs) = default;
72
+ };
73
+
74
+ } // namespace margelo::nitro::margelo::pictureselector
75
+
76
+ namespace margelo::nitro {
77
+
78
+ // C++ PictureSelectorOptions <> JS PictureSelectorOptions (object)
79
+ template <>
80
+ struct JSIConverter<margelo::nitro::margelo::pictureselector::PictureSelectorOptions> final {
81
+ static inline margelo::nitro::margelo::pictureselector::PictureSelectorOptions fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
82
+ jsi::Object obj = arg.asObject(runtime);
83
+ return margelo::nitro::margelo::pictureselector::PictureSelectorOptions(
84
+ JSIConverter<std::optional<margelo::nitro::margelo::pictureselector::MediaType>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "mediaType"))),
85
+ JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "maxCount"))),
86
+ JSIConverter<std::optional<bool>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "enableCamera"))),
87
+ JSIConverter<std::optional<margelo::nitro::margelo::pictureselector::CropOptions>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "crop"))),
88
+ JSIConverter<std::optional<margelo::nitro::margelo::pictureselector::CompressOptions>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "compress"))),
89
+ JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "maxVideoDuration"))),
90
+ JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "minVideoDuration"))),
91
+ JSIConverter<std::optional<margelo::nitro::margelo::pictureselector::PickerTheme>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "theme"))),
92
+ JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "themeColor"))),
93
+ JSIConverter<std::optional<std::vector<std::string>>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "selectedAssets")))
94
+ );
95
+ }
96
+ static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::margelo::pictureselector::PictureSelectorOptions& arg) {
97
+ jsi::Object obj(runtime);
98
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "mediaType"), JSIConverter<std::optional<margelo::nitro::margelo::pictureselector::MediaType>>::toJSI(runtime, arg.mediaType));
99
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "maxCount"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.maxCount));
100
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "enableCamera"), JSIConverter<std::optional<bool>>::toJSI(runtime, arg.enableCamera));
101
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "crop"), JSIConverter<std::optional<margelo::nitro::margelo::pictureselector::CropOptions>>::toJSI(runtime, arg.crop));
102
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "compress"), JSIConverter<std::optional<margelo::nitro::margelo::pictureselector::CompressOptions>>::toJSI(runtime, arg.compress));
103
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "maxVideoDuration"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.maxVideoDuration));
104
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "minVideoDuration"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.minVideoDuration));
105
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "theme"), JSIConverter<std::optional<margelo::nitro::margelo::pictureselector::PickerTheme>>::toJSI(runtime, arg.theme));
106
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "themeColor"), JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.themeColor));
107
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "selectedAssets"), JSIConverter<std::optional<std::vector<std::string>>>::toJSI(runtime, arg.selectedAssets));
108
+ return obj;
109
+ }
110
+ static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
111
+ if (!value.isObject()) {
112
+ return false;
113
+ }
114
+ jsi::Object obj = value.getObject(runtime);
115
+ if (!nitro::isPlainObject(runtime, obj)) {
116
+ return false;
117
+ }
118
+ if (!JSIConverter<std::optional<margelo::nitro::margelo::pictureselector::MediaType>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "mediaType")))) return false;
119
+ if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "maxCount")))) return false;
120
+ if (!JSIConverter<std::optional<bool>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "enableCamera")))) return false;
121
+ if (!JSIConverter<std::optional<margelo::nitro::margelo::pictureselector::CropOptions>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "crop")))) return false;
122
+ if (!JSIConverter<std::optional<margelo::nitro::margelo::pictureselector::CompressOptions>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "compress")))) return false;
123
+ if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "maxVideoDuration")))) return false;
124
+ if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "minVideoDuration")))) return false;
125
+ if (!JSIConverter<std::optional<margelo::nitro::margelo::pictureselector::PickerTheme>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "theme")))) return false;
126
+ if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "themeColor")))) return false;
127
+ if (!JSIConverter<std::optional<std::vector<std::string>>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "selectedAssets")))) return false;
128
+ return true;
129
+ }
130
+ };
131
+
132
+ } // namespace margelo::nitro
package/package.json ADDED
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "react-native-picture-selector",
3
+ "version": "1.0.0",
4
+ "description": "High-performance photo/video picker for React Native using Nitro Modules",
5
+ "main": "lib/commonjs/index.js",
6
+ "module": "lib/module/index.js",
7
+ "types": "lib/typescript/index.d.ts",
8
+ "react-native": "src/index.ts",
9
+ "source": "src/index.ts",
10
+ "files": [
11
+ "src",
12
+ "lib",
13
+ "android",
14
+ "ios",
15
+ "nitrogen",
16
+ "nitro.json",
17
+ "*.podspec"
18
+ ],
19
+ "scripts": {
20
+ "generate": "nitrogen src/specs",
21
+ "typecheck": "tsc --noEmit",
22
+ "build": "bob build",
23
+ "prepack": "bob build"
24
+ },
25
+ "keywords": [
26
+ "react-native",
27
+ "photo",
28
+ "video",
29
+ "picker",
30
+ "nitro",
31
+ "ios",
32
+ "android",
33
+ "camera",
34
+ "gallery"
35
+ ],
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "https://github.com/yourorg/react-native-picture-selector.git"
39
+ },
40
+ "license": "MIT",
41
+ "peerDependencies": {
42
+ "react": "*",
43
+ "react-native": "*",
44
+ "react-native-nitro-modules": ">=0.20.0"
45
+ },
46
+ "peerDependenciesMeta": {
47
+ "react-native-nitro-modules": {
48
+ "optional": false
49
+ }
50
+ },
51
+ "devDependencies": {
52
+ "@types/react": "^19.0.0",
53
+ "nitrogen": "latest",
54
+ "react-native-builder-bob": "^0.30.0",
55
+ "react-native-nitro-modules": ">=0.20.0",
56
+ "typescript": "^5.3.0"
57
+ },
58
+ "nitro": {
59
+ "ios": {
60
+ "iosModuleName": "NitroPictureSelector"
61
+ },
62
+ "android": {
63
+ "androidNamespace": "com.nitro.pictureselector",
64
+ "androidCxxLibName": "NitroPictureSelector"
65
+ }
66
+ },
67
+ "react-native-builder-bob": {
68
+ "source": "src",
69
+ "output": "lib",
70
+ "targets": [
71
+ "commonjs",
72
+ "module",
73
+ "typescript"
74
+ ]
75
+ }
76
+ }
@@ -0,0 +1,72 @@
1
+ import { NitroModules } from 'react-native-nitro-modules'
2
+ import type { HybridPictureSelector } from './specs/PictureSelector.nitro'
3
+ import type { MediaAsset, PictureSelectorOptions } from './types'
4
+ import { MediaType, toPickerError } from './types'
5
+
6
+ // ─────────────────────────────────────────────────────────────────────────────
7
+ // Lazy singleton — created once and reused across calls
8
+ // ─────────────────────────────────────────────────────────────────────────────
9
+
10
+ let _native: HybridPictureSelector | null = null
11
+
12
+ function getNative(): HybridPictureSelector {
13
+ if (_native == null) {
14
+ _native = NitroModules.createHybridObject<HybridPictureSelector>(
15
+ 'PictureSelector'
16
+ )
17
+ }
18
+ return _native
19
+ }
20
+
21
+ // ─────────────────────────────────────────────────────────────────────────────
22
+ // Default options
23
+ // ─────────────────────────────────────────────────────────────────────────────
24
+
25
+ const defaultOptions: PictureSelectorOptions = {
26
+ mediaType: MediaType.IMAGE,
27
+ maxCount: 1,
28
+ enableCamera: true,
29
+ }
30
+
31
+ // ─────────────────────────────────────────────────────────────────────────────
32
+ // Static API
33
+ // ─────────────────────────────────────────────────────────────────────────────
34
+
35
+ export const PictureSelector = {
36
+ /**
37
+ * Open the gallery picker.
38
+ *
39
+ * @example
40
+ * const assets = await PictureSelector.openPicker({ maxCount: 9 })
41
+ *
42
+ * @throws PickerError with code CANCELLED when the user dismisses
43
+ * @throws PickerError with code PERMISSION_DENIED on permission failure
44
+ */
45
+ async openPicker(
46
+ options: PictureSelectorOptions = {}
47
+ ): Promise<MediaAsset[]> {
48
+ try {
49
+ return await getNative().openPicker({ ...defaultOptions, ...options })
50
+ } catch (err) {
51
+ throw toPickerError(err)
52
+ }
53
+ },
54
+
55
+ /**
56
+ * Open the camera for capture.
57
+ *
58
+ * @example
59
+ * const [asset] = await PictureSelector.openCamera({ mediaType: MediaType.VIDEO })
60
+ *
61
+ * @throws PickerError with code CANCELLED when the user dismisses
62
+ */
63
+ async openCamera(
64
+ options: PictureSelectorOptions = {}
65
+ ): Promise<MediaAsset[]> {
66
+ try {
67
+ return await getNative().openCamera({ ...defaultOptions, ...options })
68
+ } catch (err) {
69
+ throw toPickerError(err)
70
+ }
71
+ },
72
+ }
package/src/index.ts ADDED
@@ -0,0 +1,16 @@
1
+ export { PictureSelector } from './PictureSelector'
2
+ export { usePictureSelector } from './usePictureSelector'
3
+ export type {
4
+ PictureSelectorState,
5
+ PictureSelectorActions,
6
+ UsePictureSelectorReturn,
7
+ } from './usePictureSelector'
8
+ export type {
9
+ MediaAsset,
10
+ PictureSelectorOptions,
11
+ CropOptions,
12
+ CompressOptions,
13
+ PickerResult,
14
+ PickerError,
15
+ } from './types'
16
+ export { MediaType, PickerTheme, toPickerError } from './types'
@@ -0,0 +1,121 @@
1
+ import type { HybridObject } from 'react-native-nitro-modules'
2
+
3
+ // ─────────────────────────────────────────────────────────────────────────────
4
+ // Enums
5
+ // ─────────────────────────────────────────────────────────────────────────────
6
+
7
+ export enum MediaType {
8
+ IMAGE = 'image',
9
+ VIDEO = 'video',
10
+ ALL = 'all',
11
+ }
12
+
13
+ export enum PickerTheme {
14
+ DEFAULT = 'default',
15
+ WECHAT = 'wechat',
16
+ WHITE = 'white',
17
+ DARK = 'dark',
18
+ }
19
+
20
+ // ─────────────────────────────────────────────────────────────────────────────
21
+ // Config sub-structures
22
+ // ─────────────────────────────────────────────────────────────────────────────
23
+
24
+ export interface CropOptions {
25
+ /** Enable cropping after selection */
26
+ enabled: boolean
27
+ /** Allow free-form aspect ratio. Default: false */
28
+ freeStyle?: boolean
29
+ /** Circular crop mask. iOS-only. Default: false */
30
+ circular?: boolean
31
+ /** Width part of the crop aspect ratio. Default: 1 */
32
+ ratioX?: number
33
+ /** Height part of the crop aspect ratio. Default: 1 */
34
+ ratioY?: number
35
+ }
36
+
37
+ export interface CompressOptions {
38
+ /** Enable compression */
39
+ enabled: boolean
40
+ /** JPEG quality, 0.0–1.0. Default: 0.8 */
41
+ quality?: number
42
+ /** Max output width in pixels. Default: 1920 */
43
+ maxWidth?: number
44
+ /** Max output height in pixels. Default: 1920 */
45
+ maxHeight?: number
46
+ }
47
+
48
+ // ─────────────────────────────────────────────────────────────────────────────
49
+ // Picker options
50
+ // ─────────────────────────────────────────────────────────────────────────────
51
+
52
+ export interface PictureSelectorOptions {
53
+ /** Media type to display. Default: IMAGE */
54
+ mediaType?: MediaType
55
+ /** Maximum number of selectable items. Default: 1 */
56
+ maxCount?: number
57
+ /** Show camera button inside the picker. Default: true */
58
+ enableCamera?: boolean
59
+ /** Crop configuration. Only applies when maxCount === 1 */
60
+ crop?: CropOptions
61
+ /** Compression configuration */
62
+ compress?: CompressOptions
63
+ /** Max video duration in seconds */
64
+ maxVideoDuration?: number
65
+ /** Min video duration in seconds. Default: 0 */
66
+ minVideoDuration?: number
67
+ /** Picker UI theme */
68
+ theme?: PickerTheme
69
+ /** Accent color as hex string, e.g. "#007AFF". iOS: themeColor; Android: accent */
70
+ themeColor?: string
71
+ /** Pre-selected asset URIs (file:// URIs) */
72
+ selectedAssets?: string[]
73
+ }
74
+
75
+ // ─────────────────────────────────────────────────────────────────────────────
76
+ // Result structure
77
+ // ─────────────────────────────────────────────────────────────────────────────
78
+
79
+ export interface MediaAsset {
80
+ /** file:// URI of the final file (compressed or original) */
81
+ uri: string
82
+ /** "image" | "video" */
83
+ type: string
84
+ /** MIME type, e.g. "image/jpeg", "video/mp4" */
85
+ mimeType: string
86
+ /** Width in pixels */
87
+ width: number
88
+ /** Height in pixels */
89
+ height: number
90
+ /** Duration in milliseconds (0 for images) */
91
+ duration: number
92
+ /** Original filename with extension */
93
+ fileName: string
94
+ /** File size in bytes */
95
+ fileSize: number
96
+ /** file:// URI after crop or edit. Undefined if no edit was applied */
97
+ editedUri?: string
98
+ /** iOS: true if user tapped "Original" quality button */
99
+ isOriginal?: boolean
100
+ /** Android: album/bucket name the file belongs to */
101
+ bucketName?: string
102
+ }
103
+
104
+ // ─────────────────────────────────────────────────────────────────────────────
105
+ // HybridObject — the main bridge
106
+ // ─────────────────────────────────────────────────────────────────────────────
107
+
108
+ export interface HybridPictureSelector
109
+ extends HybridObject<{ ios: 'swift'; android: 'kotlin' }> {
110
+ /**
111
+ * Open the photo/video gallery picker.
112
+ * Rejects with message "CANCELLED" when the user dismisses without selection.
113
+ */
114
+ openPicker(options: PictureSelectorOptions): Promise<MediaAsset[]>
115
+
116
+ /**
117
+ * Open the device camera for capture.
118
+ * Rejects with message "CANCELLED" when the user dismisses.
119
+ */
120
+ openCamera(options: PictureSelectorOptions): Promise<MediaAsset[]>
121
+ }
package/src/types.ts ADDED
@@ -0,0 +1,38 @@
1
+ // Re-export spec types for public consumption
2
+ export type {
3
+ MediaAsset,
4
+ PictureSelectorOptions,
5
+ CropOptions,
6
+ CompressOptions,
7
+ } from './specs/PictureSelector.nitro'
8
+
9
+ export { MediaType, PickerTheme } from './specs/PictureSelector.nitro'
10
+
11
+ // ─────────────────────────────────────────────────────────────────────────────
12
+ // Convenience aliases
13
+ // ─────────────────────────────────────────────────────────────────────────────
14
+
15
+ export type PickerResult = import('./specs/PictureSelector.nitro').MediaAsset[]
16
+
17
+ /**
18
+ * Errors thrown by openPicker / openCamera.
19
+ *
20
+ * code === 'CANCELLED' — user dismissed the picker
21
+ * code === 'PERMISSION_DENIED' — runtime permission not granted
22
+ * code === 'UNKNOWN' — any other native error
23
+ */
24
+ export interface PickerError extends Error {
25
+ code: 'CANCELLED' | 'PERMISSION_DENIED' | 'UNKNOWN'
26
+ }
27
+
28
+ /** Normalise a raw native error to a typed PickerError. */
29
+ export function toPickerError(err: unknown): PickerError {
30
+ const base = err instanceof Error ? err : new Error(String(err))
31
+ const msg = base.message ?? ''
32
+
33
+ let code: PickerError['code'] = 'UNKNOWN'
34
+ if (msg.includes('CANCELLED')) code = 'CANCELLED'
35
+ else if (msg.includes('PERMISSION_DENIED')) code = 'PERMISSION_DENIED'
36
+
37
+ return Object.assign(base, { code }) as PickerError
38
+ }
@@ -0,0 +1,102 @@
1
+ import { useState, useCallback, useRef } from 'react'
2
+ import { PictureSelector } from './PictureSelector'
3
+ import type { MediaAsset, PictureSelectorOptions, PickerError } from './types'
4
+ import { toPickerError } from './types'
5
+
6
+ // ─────────────────────────────────────────────────────────────────────────────
7
+ // Hook state shape
8
+ // ─────────────────────────────────────────────────────────────────────────────
9
+
10
+ export interface PictureSelectorState {
11
+ assets: MediaAsset[]
12
+ loading: boolean
13
+ error: PickerError | null
14
+ }
15
+
16
+ export interface PictureSelectorActions {
17
+ /** Open gallery picker */
18
+ pick: (options?: PictureSelectorOptions) => Promise<MediaAsset[]>
19
+ /** Open camera */
20
+ shoot: (options?: PictureSelectorOptions) => Promise<MediaAsset[]>
21
+ /** Clear selected assets and error state */
22
+ clear: () => void
23
+ }
24
+
25
+ export type UsePictureSelectorReturn = PictureSelectorState &
26
+ PictureSelectorActions
27
+
28
+ // ─────────────────────────────────────────────────────────────────────────────
29
+ // Hook
30
+ // ─────────────────────────────────────────────────────────────────────────────
31
+
32
+ /**
33
+ * React hook that manages picker state.
34
+ *
35
+ * @example
36
+ * const { assets, loading, pick, shoot, clear } = usePictureSelector({ maxCount: 9 })
37
+ *
38
+ * <Button onPress={() => pick()} title="Pick Photos" />
39
+ * {assets.map(a => <Image source={{ uri: a.uri }} />)}
40
+ */
41
+ export function usePictureSelector(
42
+ defaultOptions?: PictureSelectorOptions
43
+ ): UsePictureSelectorReturn {
44
+ const [state, setState] = useState<PictureSelectorState>({
45
+ assets: [],
46
+ loading: false,
47
+ error: null,
48
+ })
49
+
50
+ // Stable ref to avoid re-creating callbacks when defaultOptions changes
51
+ const defaultOptionsRef = useRef(defaultOptions)
52
+ defaultOptionsRef.current = defaultOptions
53
+
54
+ const pick = useCallback(
55
+ async (options?: PictureSelectorOptions): Promise<MediaAsset[]> => {
56
+ setState((s) => ({ ...s, loading: true, error: null }))
57
+ try {
58
+ const merged = { ...defaultOptionsRef.current, ...options }
59
+ const results = await PictureSelector.openPicker(merged)
60
+ setState({ assets: results, loading: false, error: null })
61
+ return results
62
+ } catch (err) {
63
+ const pickerErr = toPickerError(err)
64
+ // Do not surface CANCELLED as an error — just restore loading state
65
+ if (pickerErr.code === 'CANCELLED') {
66
+ setState((s) => ({ ...s, loading: false }))
67
+ return []
68
+ }
69
+ setState((s) => ({ ...s, loading: false, error: pickerErr }))
70
+ throw pickerErr
71
+ }
72
+ },
73
+ []
74
+ )
75
+
76
+ const shoot = useCallback(
77
+ async (options?: PictureSelectorOptions): Promise<MediaAsset[]> => {
78
+ setState((s) => ({ ...s, loading: true, error: null }))
79
+ try {
80
+ const merged = { ...defaultOptionsRef.current, ...options }
81
+ const results = await PictureSelector.openCamera(merged)
82
+ setState({ assets: results, loading: false, error: null })
83
+ return results
84
+ } catch (err) {
85
+ const pickerErr = toPickerError(err)
86
+ if (pickerErr.code === 'CANCELLED') {
87
+ setState((s) => ({ ...s, loading: false }))
88
+ return []
89
+ }
90
+ setState((s) => ({ ...s, loading: false, error: pickerErr }))
91
+ throw pickerErr
92
+ }
93
+ },
94
+ []
95
+ )
96
+
97
+ const clear = useCallback(() => {
98
+ setState({ assets: [], loading: false, error: null })
99
+ }, [])
100
+
101
+ return { ...state, pick, shoot, clear }
102
+ }