@codebymanan/react-native-photo-editor 0.1.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 (115) hide show
  1. package/LICENSE +20 -0
  2. package/PhotoEditor.podspec +23 -0
  3. package/README.md +200 -0
  4. package/android/build.gradle +65 -0
  5. package/android/src/main/AndroidManifest.xml +14 -0
  6. package/android/src/main/assets/beyond_wonderland.ttf +0 -0
  7. package/android/src/main/assets/emojione-android.ttf +0 -0
  8. package/android/src/main/assets/filters/auto_fix.png +0 -0
  9. package/android/src/main/assets/filters/b_n_w.png +0 -0
  10. package/android/src/main/assets/filters/brightness.png +0 -0
  11. package/android/src/main/assets/filters/contrast.png +0 -0
  12. package/android/src/main/assets/filters/cross_process.png +0 -0
  13. package/android/src/main/assets/filters/documentary.png +0 -0
  14. package/android/src/main/assets/filters/dual_tone.png +0 -0
  15. package/android/src/main/assets/filters/fill_light.png +0 -0
  16. package/android/src/main/assets/filters/fish_eye.png +0 -0
  17. package/android/src/main/assets/filters/flip_horizental.png +0 -0
  18. package/android/src/main/assets/filters/flip_vertical.png +0 -0
  19. package/android/src/main/assets/filters/grain.png +0 -0
  20. package/android/src/main/assets/filters/gray_scale.png +0 -0
  21. package/android/src/main/assets/filters/lomish.png +0 -0
  22. package/android/src/main/assets/filters/negative.png +0 -0
  23. package/android/src/main/assets/filters/original.jpg +0 -0
  24. package/android/src/main/assets/filters/posterize.png +0 -0
  25. package/android/src/main/assets/filters/rotate.png +0 -0
  26. package/android/src/main/assets/filters/saturate.png +0 -0
  27. package/android/src/main/assets/filters/sepia.png +0 -0
  28. package/android/src/main/assets/filters/sharpen.png +0 -0
  29. package/android/src/main/assets/filters/temprature.png +0 -0
  30. package/android/src/main/assets/filters/tint.png +0 -0
  31. package/android/src/main/assets/filters/vignette.png +0 -0
  32. package/android/src/main/java/com/photoeditor/PhotoEditorModule.kt +130 -0
  33. package/android/src/main/java/com/photoeditor/PhotoEditorPackage.kt +31 -0
  34. package/android/src/main/java/com/photoeditor/editor/ColorPickerAdapter.kt +100 -0
  35. package/android/src/main/java/com/photoeditor/editor/EditImageActivity.kt +407 -0
  36. package/android/src/main/java/com/photoeditor/editor/EditorLocale.kt +41 -0
  37. package/android/src/main/java/com/photoeditor/editor/EditorStrings.kt +46 -0
  38. package/android/src/main/java/com/photoeditor/editor/EmojiBSFragment.kt +121 -0
  39. package/android/src/main/java/com/photoeditor/editor/PropertiesBSFragment.kt +76 -0
  40. package/android/src/main/java/com/photoeditor/editor/ShapeBSFragment.kt +112 -0
  41. package/android/src/main/java/com/photoeditor/editor/StickerBSFragment.kt +130 -0
  42. package/android/src/main/java/com/photoeditor/editor/TextEditorDialogFragment.kt +133 -0
  43. package/android/src/main/java/com/photoeditor/editor/base/BaseActivity.kt +67 -0
  44. package/android/src/main/java/com/photoeditor/editor/base/BaseFragment.kt +10 -0
  45. package/android/src/main/java/com/photoeditor/editor/filters/FilterListener.kt +7 -0
  46. package/android/src/main/java/com/photoeditor/editor/filters/FilterViewAdapter.kt +105 -0
  47. package/android/src/main/java/com/photoeditor/editor/tools/EditingToolsAdapter.kt +70 -0
  48. package/android/src/main/java/com/photoeditor/editor/tools/ToolType.kt +10 -0
  49. package/android/src/main/res/drawable/pe_blank_image.jpg +0 -0
  50. package/android/src/main/res/drawable/pe_ic_brush.xml +9 -0
  51. package/android/src/main/res/drawable/pe_ic_close.xml +9 -0
  52. package/android/src/main/res/drawable/pe_ic_eraser.xml +4 -0
  53. package/android/src/main/res/drawable/pe_ic_insert_emoticon.xml +9 -0
  54. package/android/src/main/res/drawable/pe_ic_oval.xml +9 -0
  55. package/android/src/main/res/drawable/pe_ic_photo_filter.xml +5 -0
  56. package/android/src/main/res/drawable/pe_ic_rectangle.xml +9 -0
  57. package/android/src/main/res/drawable/pe_ic_redo.xml +10 -0
  58. package/android/src/main/res/drawable/pe_ic_redo_disabled.xml +10 -0
  59. package/android/src/main/res/drawable/pe_ic_save.xml +9 -0
  60. package/android/src/main/res/drawable/pe_ic_sticker.xml +9 -0
  61. package/android/src/main/res/drawable/pe_ic_text.xml +9 -0
  62. package/android/src/main/res/drawable/pe_ic_undo.xml +10 -0
  63. package/android/src/main/res/drawable/pe_ic_undo_disabled.xml +10 -0
  64. package/android/src/main/res/drawable/pe_original.jpg +0 -0
  65. package/android/src/main/res/drawable/pe_redo.xml +6 -0
  66. package/android/src/main/res/drawable/pe_rounded_border_text_view.xml +14 -0
  67. package/android/src/main/res/drawable/pe_undo.xml +6 -0
  68. package/android/src/main/res/font/pe_roboto_medium.xml +7 -0
  69. package/android/src/main/res/layout/pe_activity_edit_image.xml +111 -0
  70. package/android/src/main/res/layout/pe_add_text_dialog.xml +56 -0
  71. package/android/src/main/res/layout/pe_color_picker_item_list.xml +15 -0
  72. package/android/src/main/res/layout/pe_fragment_bottom_properties_dialog.xml +77 -0
  73. package/android/src/main/res/layout/pe_fragment_bottom_shapes_dialog.xml +135 -0
  74. package/android/src/main/res/layout/pe_fragment_bottom_sticker_emoji_dialog.xml +62 -0
  75. package/android/src/main/res/layout/pe_row_editing_tools.xml +34 -0
  76. package/android/src/main/res/layout/pe_row_emoji.xml +17 -0
  77. package/android/src/main/res/layout/pe_row_filter_view.xml +35 -0
  78. package/android/src/main/res/layout/pe_row_sticker.xml +23 -0
  79. package/android/src/main/res/values/colors.xml +22 -0
  80. package/android/src/main/res/values/dimens.xml +7 -0
  81. package/android/src/main/res/values/font_certs.xml +17 -0
  82. package/android/src/main/res/values/preloaded_fonts.xml +6 -0
  83. package/android/src/main/res/values/strings.xml +462 -0
  84. package/android/src/main/res/values/styles.xml +28 -0
  85. package/ios/PhotoEditor.h +5 -0
  86. package/ios/PhotoEditor.mm +58 -0
  87. package/ios/PhotoEditorManager.swift +164 -0
  88. package/lib/module/NativePhotoEditor.js +5 -0
  89. package/lib/module/NativePhotoEditor.js.map +1 -0
  90. package/lib/module/index.js +4 -0
  91. package/lib/module/index.js.map +1 -0
  92. package/lib/module/open.js +6 -0
  93. package/lib/module/open.js.map +1 -0
  94. package/lib/module/open.native.js +7 -0
  95. package/lib/module/open.native.js.map +1 -0
  96. package/lib/module/package.json +1 -0
  97. package/lib/module/types.js +2 -0
  98. package/lib/module/types.js.map +1 -0
  99. package/lib/typescript/package.json +1 -0
  100. package/lib/typescript/src/NativePhotoEditor.d.ts +14 -0
  101. package/lib/typescript/src/NativePhotoEditor.d.ts.map +1 -0
  102. package/lib/typescript/src/index.d.ts +3 -0
  103. package/lib/typescript/src/index.d.ts.map +1 -0
  104. package/lib/typescript/src/open.d.ts +3 -0
  105. package/lib/typescript/src/open.d.ts.map +1 -0
  106. package/lib/typescript/src/open.native.d.ts +3 -0
  107. package/lib/typescript/src/open.native.d.ts.map +1 -0
  108. package/lib/typescript/src/types.d.ts +39 -0
  109. package/lib/typescript/src/types.d.ts.map +1 -0
  110. package/package.json +128 -0
  111. package/src/NativePhotoEditor.ts +12 -0
  112. package/src/index.tsx +2 -0
  113. package/src/open.native.tsx +6 -0
  114. package/src/open.tsx +7 -0
  115. package/src/types.ts +36 -0
@@ -0,0 +1,5 @@
1
+ #import <PhotoEditorSpec/PhotoEditorSpec.h>
2
+
3
+ @interface PhotoEditor : NSObject <NativePhotoEditorSpec>
4
+
5
+ @end
@@ -0,0 +1,58 @@
1
+ #import "PhotoEditor.h"
2
+
3
+ #if __has_include("PhotoEditor/PhotoEditor-Swift.h")
4
+ #import "PhotoEditor/PhotoEditor-Swift.h"
5
+ #else
6
+ #import "PhotoEditor-Swift.h"
7
+ #endif
8
+
9
+ @implementation PhotoEditor
10
+
11
+ - (void)open:(JS::NativePhotoEditor::SpecOpenOptions &)options
12
+ resolve:(RCTPromiseResolveBlock)resolve
13
+ reject:(RCTPromiseRejectBlock)reject
14
+ {
15
+ NSString *path = options.path();
16
+ if (path.length == 0) {
17
+ reject(@"E_INVALID_OPTIONS", @"Missing required option: path", nil);
18
+ return;
19
+ }
20
+
21
+ NSMutableArray<NSString *> *stickers = [NSMutableArray new];
22
+ if (options.stickers().has_value()) {
23
+ auto vector = options.stickers().value();
24
+ for (size_t i = 0; i < vector.size(); i++) {
25
+ [stickers addObject:vector[i]];
26
+ }
27
+ }
28
+
29
+ // Codegen hands dictionaries back untyped, so check before casting.
30
+ id rawTranslations = options.translations();
31
+ NSDictionary *translations = [rawTranslations isKindOfClass:[NSDictionary class]]
32
+ ? (NSDictionary *)rawTranslations
33
+ : nil;
34
+
35
+ [PhotoEditorManager open:path
36
+ stickers:stickers
37
+ language:options.language()
38
+ translations:translations
39
+ resolve:^(NSString *outputPath) {
40
+ resolve(outputPath);
41
+ }
42
+ reject:^(NSString *code, NSString *message) {
43
+ reject(code, message, nil);
44
+ }];
45
+ }
46
+
47
+ - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
48
+ (const facebook::react::ObjCTurboModule::InitParams &)params
49
+ {
50
+ return std::make_shared<facebook::react::NativePhotoEditorSpecJSI>(params);
51
+ }
52
+
53
+ + (NSString *)moduleName
54
+ {
55
+ return @"PhotoEditor";
56
+ }
57
+
58
+ @end
@@ -0,0 +1,164 @@
1
+ import UIKit
2
+ import ZLImageEditor
3
+
4
+ @objc(PhotoEditorManager)
5
+ public class PhotoEditorManager: NSObject {
6
+
7
+ @objc public static func open(
8
+ _ path: String,
9
+ stickers: [String],
10
+ language: String?,
11
+ translations: [String: Any]?,
12
+ resolve: @escaping (String) -> Void,
13
+ reject: @escaping (String, String) -> Void
14
+ ) {
15
+ loadImage(path) { image in
16
+ DispatchQueue.main.async {
17
+ guard let image else {
18
+ reject("E_FAILED", "Could not load image: \(path)")
19
+ return
20
+ }
21
+ guard let presenter = topViewController() else {
22
+ reject("E_NO_ACTIVITY", "No view controller available to present the editor")
23
+ return
24
+ }
25
+
26
+ ZLImageEditorUIConfiguration.default()
27
+ .languageType(languageType(for: language))
28
+ .customLanguageConfig(customLanguage(from: translations))
29
+
30
+ ZLImageEditorConfiguration.default()
31
+ .editImageTools([.draw, .clip, .textSticker, .mosaic, .filter, .adjust])
32
+ .adjustTools([.brightness, .contrast, .saturation])
33
+
34
+ let editor = ZLEditImageViewController(image: image)
35
+ editor.modalPresentationStyle = .fullScreen
36
+ editor.editFinishBlock = { resImage, _ in
37
+ saveImage(resImage, resolve: resolve, reject: reject)
38
+ }
39
+ editor.cancelBlock = {
40
+ reject("E_CANCELLED", "User cancelled image editing")
41
+ }
42
+ presenter.present(editor, animated: true)
43
+ }
44
+ }
45
+ }
46
+
47
+ /// The editor exposes exactly these nine strings for overriding, so this is
48
+ /// the whole of what `translations` can reach on iOS. Keys are the same ones
49
+ /// Android uses, which is what lets one map drive both platforms.
50
+ private static let overridableKeys: [String: ZLLocalLanguageKey] = [
51
+ "pe_label_cancel": .cancel,
52
+ "pe_label_done": .done,
53
+ "pe_label_save": .editFinish,
54
+ "pe_label_undo": .revert,
55
+ "pe_filter_brightness": .brightness,
56
+ "pe_filter_contrast": .contrast,
57
+ "pe_filter_saturate": .saturation,
58
+ "pe_msg_drag_to_remove": .textStickerRemoveTips,
59
+ "pe_msg_saving": .hudProcessing,
60
+ ]
61
+
62
+ /// Always returns a dictionary, empty included: the configuration is a shared
63
+ /// singleton, so anything left unassigned would outlive the call that set it.
64
+ private static func customLanguage(from translations: [String: Any]?) -> [ZLLocalLanguageKey: String] {
65
+ guard let translations else { return [:] }
66
+
67
+ return overridableKeys.reduce(into: [:]) { config, entry in
68
+ // Non-string values are dropped rather than coerced, so a mistyped entry
69
+ // falls back to the built-in string.
70
+ if let value = translations[entry.key] as? String, !value.isEmpty {
71
+ config[entry.value] = value
72
+ }
73
+ }
74
+ }
75
+
76
+ /// Maps a BCP-47 tag onto the languages the editor ships.
77
+ ///
78
+ /// A missing tag means "follow the device". An unrecognised tag falls back to
79
+ /// English rather than to the device language: the caller explicitly asked not
80
+ /// to use the device setting, so quietly reverting to it would be the one
81
+ /// answer we know they did not want.
82
+ private static func languageType(for tag: String?) -> ZLImageEditorLanguageType {
83
+ guard let tag = tag?.lowercased(), !tag.isEmpty else { return .system }
84
+
85
+ // Tolerate the Java-style "pt_BR" spelling as well as BCP-47's "pt-BR".
86
+ let subtags = tag.split(whereSeparator: { $0 == "-" || $0 == "_" }).map(String.init)
87
+
88
+ // Chinese needs the script or region, not just the language, to pick a bundle.
89
+ if subtags.first == "zh" {
90
+ let traditional = subtags.dropFirst().contains { ["hant", "tw", "hk", "mo"].contains($0) }
91
+ return traditional ? .chineseTraditional : .chineseSimplified
92
+ }
93
+
94
+ switch subtags.first ?? tag {
95
+ case "en": return .english
96
+ case "ja": return .japanese
97
+ case "fr": return .french
98
+ case "de": return .german
99
+ case "ru": return .russian
100
+ case "vi": return .vietnamese
101
+ case "ko": return .korean
102
+ case "ms": return .malay
103
+ case "it": return .italian
104
+ case "id", "in": return .indonesian
105
+ case "pt": return .portuguese
106
+ case "es": return .spanish
107
+ case "tr": return .turkish
108
+ case "ar": return .arabic
109
+ case "uk": return .ukrainian
110
+ case "nl": return .dutch
111
+ default: return .english
112
+ }
113
+ }
114
+
115
+ private static func loadImage(_ path: String, completion: @escaping (UIImage?) -> Void) {
116
+ if path.hasPrefix("http://") || path.hasPrefix("https://") {
117
+ guard let url = URL(string: path) else {
118
+ completion(nil)
119
+ return
120
+ }
121
+ URLSession.shared.dataTask(with: url) { data, _, _ in
122
+ completion(data.flatMap(UIImage.init(data:)))
123
+ }.resume()
124
+ } else {
125
+ let filePath = path.hasPrefix("file://") ? String(path.dropFirst(7)) : path
126
+ completion(UIImage(contentsOfFile: filePath))
127
+ }
128
+ }
129
+
130
+ private static func saveImage(
131
+ _ image: UIImage,
132
+ resolve: @escaping (String) -> Void,
133
+ reject: @escaping (String, String) -> Void
134
+ ) {
135
+ let outputDir = (NSTemporaryDirectory() as NSString).appendingPathComponent("photo_editor")
136
+ do {
137
+ try FileManager.default.createDirectory(
138
+ atPath: outputDir, withIntermediateDirectories: true)
139
+ let outputPath = (outputDir as NSString)
140
+ .appendingPathComponent("\(Int(Date().timeIntervalSince1970 * 1000)).png")
141
+ guard let data = image.pngData() else {
142
+ reject("E_FAILED", "Could not encode edited image")
143
+ return
144
+ }
145
+ try data.write(to: URL(fileURLWithPath: outputPath))
146
+ resolve(outputPath)
147
+ } catch {
148
+ reject("E_FAILED", "Failed to save image: \(error.localizedDescription)")
149
+ }
150
+ }
151
+
152
+ private static func topViewController() -> UIViewController? {
153
+ let keyWindow = UIApplication.shared.connectedScenes
154
+ .compactMap { $0 as? UIWindowScene }
155
+ .flatMap { $0.windows }
156
+ .first { $0.isKeyWindow }
157
+
158
+ var top = keyWindow?.rootViewController
159
+ while let presented = top?.presentedViewController {
160
+ top = presented
161
+ }
162
+ return top
163
+ }
164
+ }
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+
3
+ import { TurboModuleRegistry } from 'react-native';
4
+ export default TurboModuleRegistry.getEnforcing('PhotoEditor');
5
+ //# sourceMappingURL=NativePhotoEditor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativePhotoEditor.ts"],"mappings":";;AAAA,SAASA,mBAAmB,QAA0B,cAAc;AAWpE,eAAeA,mBAAmB,CAACC,YAAY,CAAO,aAAa,CAAC","ignoreList":[]}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+
3
+ export { open } from './open';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["open"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SAASA,IAAI,QAAQ,QAAQ","ignoreList":[]}
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+
3
+ export function open(_options) {
4
+ throw new Error("'@codebymanan/react-native-photo-editor' is only supported on native platforms.");
5
+ }
6
+ //# sourceMappingURL=open.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["open","_options","Error"],"sourceRoot":"../../src","sources":["open.tsx"],"mappings":";;AAEA,OAAO,SAASA,IAAIA,CAACC,QAA4B,EAAmB;EAClE,MAAM,IAAIC,KAAK,CACb,iFACF,CAAC;AACH","ignoreList":[]}
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+
3
+ import PhotoEditor from "./NativePhotoEditor.js";
4
+ export function open(options) {
5
+ return PhotoEditor.open(options);
6
+ }
7
+ //# sourceMappingURL=open.native.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["PhotoEditor","open","options"],"sourceRoot":"../../src","sources":["open.native.tsx"],"mappings":";;AAAA,OAAOA,WAAW,MAAM,wBAAqB;AAG7C,OAAO,SAASC,IAAIA,CAACC,OAA2B,EAAmB;EACjE,OAAOF,WAAW,CAACC,IAAI,CAACC,OAAO,CAAC;AAClC","ignoreList":[]}
@@ -0,0 +1 @@
1
+ {"type":"module"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sourceRoot":"../../src","sources":["types.ts"],"mappings":"","ignoreList":[]}
@@ -0,0 +1 @@
1
+ {"type":"module"}
@@ -0,0 +1,14 @@
1
+ import { type TurboModule } from 'react-native';
2
+ export interface Spec extends TurboModule {
3
+ open(options: {
4
+ path: string;
5
+ stickers?: string[];
6
+ language?: string;
7
+ translations?: {
8
+ [key: string]: string;
9
+ };
10
+ }): Promise<string>;
11
+ }
12
+ declare const _default: Spec;
13
+ export default _default;
14
+ //# sourceMappingURL=NativePhotoEditor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NativePhotoEditor.d.ts","sourceRoot":"","sources":["../../../src/NativePhotoEditor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAErE,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,IAAI,CAAC,OAAO,EAAE;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,YAAY,CAAC,EAAE;YAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;SAAE,CAAC;KAC1C,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACrB;;AAED,wBAAqE"}
@@ -0,0 +1,3 @@
1
+ export { open } from './open';
2
+ export type { PhotoEditorOptions } from './types.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,YAAY,EAAE,kBAAkB,EAAE,MAAM,YAAS,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { PhotoEditorOptions } from './types.js';
2
+ export declare function open(_options: PhotoEditorOptions): Promise<string>;
3
+ //# sourceMappingURL=open.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open.d.ts","sourceRoot":"","sources":["../../../src/open.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAS,CAAC;AAElD,wBAAgB,IAAI,CAAC,QAAQ,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAIlE"}
@@ -0,0 +1,3 @@
1
+ import type { PhotoEditorOptions } from './types.js';
2
+ export declare function open(options: PhotoEditorOptions): Promise<string>;
3
+ //# sourceMappingURL=open.native.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open.native.d.ts","sourceRoot":"","sources":["../../../src/open.native.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAS,CAAC;AAElD,wBAAgB,IAAI,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAEjE"}
@@ -0,0 +1,39 @@
1
+ export interface PhotoEditorOptions {
2
+ /**
3
+ * The image to edit. Accepts a local file path, `file://` or `content://`
4
+ * URI, or a remote `http(s)` URL.
5
+ */
6
+ path: string;
7
+ /**
8
+ * Optional list of sticker image URLs shown in the sticker picker.
9
+ */
10
+ stickers?: string[];
11
+ /**
12
+ * BCP-47 language tag (`'fr'`, `'pt-BR'`, `'zh-Hans'`) for the editor UI.
13
+ *
14
+ * Defaults to the device language. Set this only when your app has its own
15
+ * language picker and needs the editor to follow it rather than the device.
16
+ *
17
+ * On Android the tag selects a `values-<lang>` resource folder, so it can be
18
+ * any language your app provides strings for. On iOS it maps onto the
19
+ * languages the underlying editor ships; unsupported tags fall back to
20
+ * English.
21
+ */
22
+ language?: string;
23
+ /**
24
+ * Per-key string overrides, keyed by the editor's string names
25
+ * (`pe_label_save`, `pe_filter_contrast`, ...). See the README for the list.
26
+ *
27
+ * Use this when your strings live in JS rather than in native resources, or
28
+ * to reach a language iOS does not ship. Keys you leave out keep their
29
+ * built-in value, and on Android anything you have already put in a
30
+ * `values-<lang>` folder still applies underneath.
31
+ *
32
+ * Android honours every key. iOS honours the nine the underlying editor
33
+ * exposes; the rest are ignored there.
34
+ */
35
+ translations?: {
36
+ [key: string]: string;
37
+ };
38
+ }
39
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;;;;;;OAWG;IACH,YAAY,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;CAC1C"}
package/package.json ADDED
@@ -0,0 +1,128 @@
1
+ {
2
+ "name": "@codebymanan/react-native-photo-editor",
3
+ "version": "0.1.0",
4
+ "description": "A React Native photo editor plugin wrapping native editors for Android and iOS",
5
+ "main": "./lib/module/index.js",
6
+ "types": "./lib/typescript/src/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "react-native-photo-editor-source": "./src/index.tsx",
10
+ "types": "./lib/typescript/src/index.d.ts",
11
+ "default": "./lib/module/index.js"
12
+ },
13
+ "./package.json": "./package.json"
14
+ },
15
+ "files": [
16
+ "src",
17
+ "lib",
18
+ "android",
19
+ "ios",
20
+ "cpp",
21
+ "*.podspec",
22
+ "react-native.config.js",
23
+ "!ios/build",
24
+ "!android/build",
25
+ "!android/gradle",
26
+ "!android/gradlew",
27
+ "!android/gradlew.bat",
28
+ "!android/local.properties",
29
+ "!**/__tests__",
30
+ "!**/__fixtures__",
31
+ "!**/__mocks__",
32
+ "!**/.*"
33
+ ],
34
+ "scripts": {
35
+ "example": "yarn workspace react-native-photo-editor-example",
36
+ "clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib",
37
+ "prepare": "bob build",
38
+ "typecheck": "tsc",
39
+ "lint": "eslint \"**/*.{js,ts,tsx}\""
40
+ },
41
+ "keywords": [
42
+ "react-native",
43
+ "ios",
44
+ "android"
45
+ ],
46
+ "repository": {
47
+ "type": "git",
48
+ "url": "git+https://github.com/codebymanan/react-native-photo-editor.git"
49
+ },
50
+ "author": "Abdul Manan <abdulmanancoder@gmail.com> (https://github.com/codebymanan)",
51
+ "license": "MIT",
52
+ "bugs": {
53
+ "url": "https://github.com/codebymanan/react-native-photo-editor/issues"
54
+ },
55
+ "homepage": "https://github.com/codebymanan/react-native-photo-editor#readme",
56
+ "publishConfig": {
57
+ "registry": "https://registry.npmjs.org/",
58
+ "access": "public"
59
+ },
60
+ "devDependencies": {
61
+ "@eslint/compat": "^2.1.0",
62
+ "@eslint/eslintrc": "^3.3.5",
63
+ "@eslint/js": "^10.0.1",
64
+ "@react-native/babel-preset": "0.85.0",
65
+ "@react-native/eslint-config": "0.85.0",
66
+ "@types/react": "^19.2.0",
67
+ "del-cli": "^7.0.0",
68
+ "eslint": "^9.39.4",
69
+ "eslint-config-prettier": "^10.1.8",
70
+ "eslint-plugin-ft-flow": "^3.0.11",
71
+ "eslint-plugin-prettier": "^5.5.6",
72
+ "prettier": "^3.8.3",
73
+ "react": "19.2.3",
74
+ "react-native": "0.85.0",
75
+ "react-native-builder-bob": "^0.43.0",
76
+ "turbo": "^2.9.16",
77
+ "typescript": "^6.0.3"
78
+ },
79
+ "peerDependencies": {
80
+ "react": "*",
81
+ "react-native": "*"
82
+ },
83
+ "workspaces": [
84
+ "example"
85
+ ],
86
+ "packageManager": "yarn@4.11.0",
87
+ "react-native-builder-bob": {
88
+ "source": "src",
89
+ "output": "lib",
90
+ "targets": [
91
+ [
92
+ "module",
93
+ {
94
+ "esm": true
95
+ }
96
+ ],
97
+ [
98
+ "typescript",
99
+ {
100
+ "project": "tsconfig.build.json"
101
+ }
102
+ ]
103
+ ]
104
+ },
105
+ "codegenConfig": {
106
+ "name": "PhotoEditorSpec",
107
+ "type": "modules",
108
+ "jsSrcsDir": "src",
109
+ "android": {
110
+ "javaPackageName": "com.photoeditor"
111
+ }
112
+ },
113
+ "prettier": {
114
+ "quoteProps": "consistent",
115
+ "singleQuote": true,
116
+ "tabWidth": 2,
117
+ "trailingComma": "es5",
118
+ "useTabs": false
119
+ },
120
+ "create-react-native-library": {
121
+ "type": "turbo-module",
122
+ "languages": "kotlin-objc",
123
+ "tools": [
124
+ "eslint"
125
+ ],
126
+ "version": "0.63.0"
127
+ }
128
+ }
@@ -0,0 +1,12 @@
1
+ import { TurboModuleRegistry, type TurboModule } from 'react-native';
2
+
3
+ export interface Spec extends TurboModule {
4
+ open(options: {
5
+ path: string;
6
+ stickers?: string[];
7
+ language?: string;
8
+ translations?: { [key: string]: string };
9
+ }): Promise<string>;
10
+ }
11
+
12
+ export default TurboModuleRegistry.getEnforcing<Spec>('PhotoEditor');
package/src/index.tsx ADDED
@@ -0,0 +1,2 @@
1
+ export { open } from './open';
2
+ export type { PhotoEditorOptions } from './types';
@@ -0,0 +1,6 @@
1
+ import PhotoEditor from './NativePhotoEditor';
2
+ import type { PhotoEditorOptions } from './types';
3
+
4
+ export function open(options: PhotoEditorOptions): Promise<string> {
5
+ return PhotoEditor.open(options);
6
+ }
package/src/open.tsx ADDED
@@ -0,0 +1,7 @@
1
+ import type { PhotoEditorOptions } from './types';
2
+
3
+ export function open(_options: PhotoEditorOptions): Promise<string> {
4
+ throw new Error(
5
+ "'@codebymanan/react-native-photo-editor' is only supported on native platforms."
6
+ );
7
+ }
package/src/types.ts ADDED
@@ -0,0 +1,36 @@
1
+ export interface PhotoEditorOptions {
2
+ /**
3
+ * The image to edit. Accepts a local file path, `file://` or `content://`
4
+ * URI, or a remote `http(s)` URL.
5
+ */
6
+ path: string;
7
+ /**
8
+ * Optional list of sticker image URLs shown in the sticker picker.
9
+ */
10
+ stickers?: string[];
11
+ /**
12
+ * BCP-47 language tag (`'fr'`, `'pt-BR'`, `'zh-Hans'`) for the editor UI.
13
+ *
14
+ * Defaults to the device language. Set this only when your app has its own
15
+ * language picker and needs the editor to follow it rather than the device.
16
+ *
17
+ * On Android the tag selects a `values-<lang>` resource folder, so it can be
18
+ * any language your app provides strings for. On iOS it maps onto the
19
+ * languages the underlying editor ships; unsupported tags fall back to
20
+ * English.
21
+ */
22
+ language?: string;
23
+ /**
24
+ * Per-key string overrides, keyed by the editor's string names
25
+ * (`pe_label_save`, `pe_filter_contrast`, ...). See the README for the list.
26
+ *
27
+ * Use this when your strings live in JS rather than in native resources, or
28
+ * to reach a language iOS does not ship. Keys you leave out keep their
29
+ * built-in value, and on Android anything you have already put in a
30
+ * `values-<lang>` folder still applies underneath.
31
+ *
32
+ * Android honours every key. iOS honours the nine the underlying editor
33
+ * exposes; the rest are ignored there.
34
+ */
35
+ translations?: { [key: string]: string };
36
+ }