@phucprime/react-native-image-editor 1.0.2 → 1.0.4

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 (38) hide show
  1. package/README.md +51 -31
  2. package/android/build.gradle +5 -1
  3. package/android/libs/README.md +7 -0
  4. package/android/libs/photo-editor-android.jar +0 -0
  5. package/android/src/main/java/ui/photoeditor/RNPhotoEditorModule.java +155 -60
  6. package/android/src/main/java/ui/photoeditor/RNPhotoEditorPackage.java +50 -12
  7. package/android/src/main/res/layout/photo_editor_sdk_image_item_list.xml +16 -0
  8. package/android/src/main/res/layout/photo_editor_sdk_text_item_list.xml +13 -0
  9. package/android/src/newarch/java/ui/photoeditor/RNPhotoEditorSpec.java +10 -2
  10. package/android/src/oldarch/java/ui/photoeditor/RNPhotoEditorSpec.java +22 -4
  11. package/ios/RNImageEditor.podspec +39 -8
  12. package/ios/RNPhotoEditor.mm +32 -6
  13. package/ios/RNPhotoEditor.swift +178 -95
  14. package/lib/commonjs/NativeRNPhotoEditor.js +41 -0
  15. package/lib/commonjs/NativeRNPhotoEditor.js.map +1 -0
  16. package/lib/commonjs/index.js +142 -0
  17. package/lib/commonjs/index.js.map +1 -0
  18. package/lib/commonjs/package.json +1 -0
  19. package/lib/module/NativeRNPhotoEditor.js +40 -0
  20. package/lib/module/NativeRNPhotoEditor.js.map +1 -0
  21. package/lib/module/index.js +140 -0
  22. package/lib/module/index.js.map +1 -0
  23. package/lib/typescript/NativeRNPhotoEditor.d.ts +46 -0
  24. package/lib/typescript/NativeRNPhotoEditor.d.ts.map +1 -0
  25. package/lib/{index.d.ts → typescript/index.d.ts} +44 -34
  26. package/lib/typescript/index.d.ts.map +1 -0
  27. package/package.json +53 -22
  28. package/react-native-image-editor.podspec +8 -5
  29. package/src/NativeRNPhotoEditor.ts +38 -8
  30. package/src/index.ts +85 -80
  31. package/ios/RNPhotoEditor.m +0 -24
  32. package/lib/NativeRNPhotoEditor.d.ts +0 -14
  33. package/lib/NativeRNPhotoEditor.d.ts.map +0 -1
  34. package/lib/NativeRNPhotoEditor.js +0 -5
  35. package/lib/NativeRNPhotoEditor.js.map +0 -1
  36. package/lib/index.d.ts.map +0 -1
  37. package/lib/index.js +0 -120
  38. package/lib/index.js.map +0 -1
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+
3
+ import NativeRNPhotoEditor from './NativeRNPhotoEditor';
4
+
5
+ /**
6
+ * Localization strings for the image editor UI.
7
+ * All fields are optional — unset keys fall back to the English defaults.
8
+ */
9
+
10
+ /**
11
+ * Editor control identifiers that can be hidden via `hiddenControls`.
12
+ */
13
+
14
+ /**
15
+ * Configuration options for the image editor.
16
+ */
17
+
18
+ // ─── Defaults ────────────────────────────────────────────────────────────────
19
+
20
+ /** Built-in 13-colour drawing palette. */
21
+ const DEFAULT_COLORS = ['#000000', '#808080', '#a9a9a9', '#FFFFFE', '#0000ff', '#00ff00', '#ff0000', '#ffff00', '#ffa500', '#800080', '#00ffff', '#a52a2a', '#ff00ff'];
22
+
23
+ /** Built-in English UI strings. */
24
+ const DEFAULT_LANGUAGES = {
25
+ doneTitle: 'Done',
26
+ saveTitle: 'Save',
27
+ clearAllTitle: 'Clear all',
28
+ cameraTitle: 'Camera',
29
+ galleryTitle: 'Gallery',
30
+ uploadDialogTitle: 'Upload Image',
31
+ uploadPickerTitle: 'Select Picture',
32
+ directoryCreateFail: 'Failed to create directory',
33
+ accessMediaPermissionsMsg: 'To attach photos, we need to access media on your device',
34
+ continueTxt: 'Continue',
35
+ notNow: 'NOT NOW',
36
+ mediaAccessDeniedMsg: 'You denied storage access, no photos will be added.',
37
+ saveImageSucceed: 'Image saved',
38
+ eraserTitle: 'Eraser'
39
+ };
40
+
41
+ // ─── Core native call ─────────────────────────────────────────────────────────
42
+
43
+ /**
44
+ * Build the props object and call the native TurboModule.
45
+ *
46
+ * The native module exposes a single `edit(props): Promise<string>` method.
47
+ * This is the only point in the codebase that touches the native boundary,
48
+ * keeping the public API (open / edit) as thin wrappers.
49
+ */
50
+ function callNative(config) {
51
+ const {
52
+ path,
53
+ stickers = [],
54
+ hiddenControls = [],
55
+ colors = DEFAULT_COLORS,
56
+ languages
57
+ } = config;
58
+ const mergedLanguages = languages ? {
59
+ ...DEFAULT_LANGUAGES,
60
+ ...languages
61
+ } : DEFAULT_LANGUAGES;
62
+ return NativeRNPhotoEditor.edit({
63
+ path,
64
+ colors,
65
+ hiddenControls,
66
+ stickers,
67
+ languages: mergedLanguages
68
+ });
69
+ }
70
+
71
+ // ─── Public API ───────────────────────────────────────────────────────────────
72
+
73
+ /**
74
+ * React Native Image Editor — native photo editing for iOS and Android.
75
+ *
76
+ * Supports the New Architecture (Fabric + TurboModules) and the classic bridge.
77
+ *
78
+ * @example
79
+ * ```ts
80
+ * // Promise / async-await (recommended)
81
+ * const saved = await ImageEditor.edit('/path/to/photo.jpg', {
82
+ * colors: ['#ff0000', '#00ff00', '#0000ff'],
83
+ * stickers: ['heart', 'star'],
84
+ * });
85
+ *
86
+ * // Callback
87
+ * ImageEditor.open({
88
+ * path: '/path/to/photo.jpg',
89
+ * onDone: (path) => console.log('saved:', path),
90
+ * onCancel: () => console.log('cancelled'),
91
+ * });
92
+ * ```
93
+ */
94
+ class ImageEditor {
95
+ /**
96
+ * Edit an image and receive the result via callbacks.
97
+ *
98
+ * @param config - Editor configuration including `onDone` / `onCancel`.
99
+ */
100
+ static open(config) {
101
+ callNative(config).then(config.onDone).catch(() => config.onCancel?.());
102
+ }
103
+
104
+ /**
105
+ * Edit an image and return a Promise.
106
+ *
107
+ * Resolves with the saved image path.
108
+ * Rejects with `{ code: 'CANCELLED' }` when the user dismisses.
109
+ *
110
+ * @param path - Local file path of the image to edit.
111
+ * @param options - Optional editor configuration (excludes path, onDone, onCancel).
112
+ */
113
+ static edit(path, options) {
114
+ return callNative({
115
+ ...options,
116
+ path
117
+ });
118
+ }
119
+
120
+ /**
121
+ * @deprecated Use `ImageEditor.open()` instead.
122
+ */
123
+ static Edit(config) {
124
+ ImageEditor.open(config);
125
+ }
126
+ }
127
+
128
+ // ─── Exports ──────────────────────────────────────────────────────────────────
129
+
130
+ /**
131
+ * @deprecated Use `ImageEditor` instead.
132
+ */
133
+ const PhotoEditor = ImageEditor;
134
+ export { ImageEditor, PhotoEditor };
135
+ export default ImageEditor;
136
+
137
+ /** @deprecated Use `ImageEditorConfig` instead. */
138
+
139
+ /** @deprecated Use `ImageEditorLanguage` instead. */
140
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["NativeRNPhotoEditor","DEFAULT_COLORS","DEFAULT_LANGUAGES","doneTitle","saveTitle","clearAllTitle","cameraTitle","galleryTitle","uploadDialogTitle","uploadPickerTitle","directoryCreateFail","accessMediaPermissionsMsg","continueTxt","notNow","mediaAccessDeniedMsg","saveImageSucceed","eraserTitle","callNative","config","path","stickers","hiddenControls","colors","languages","mergedLanguages","edit","ImageEditor","open","then","onDone","catch","onCancel","options","Edit","PhotoEditor"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;AAAA,OAAOA,mBAAmB,MAAM,uBAAuB;;AAEvD;AACA;AACA;AACA;;AAgCA;AACA;AACA;;AAUA;AACA;AACA;;AAgDA;;AAEA;AACA,MAAMC,cAAwB,GAAG,CAC/B,SAAS,EACT,SAAS,EACT,SAAS,EACT,SAAS,EACT,SAAS,EACT,SAAS,EACT,SAAS,EACT,SAAS,EACT,SAAS,EACT,SAAS,EACT,SAAS,EACT,SAAS,EACT,SAAS,CACV;;AAED;AACA,MAAMC,iBAAgD,GAAG;EACvDC,SAAS,EAAE,MAAM;EACjBC,SAAS,EAAE,MAAM;EACjBC,aAAa,EAAE,WAAW;EAC1BC,WAAW,EAAE,QAAQ;EACrBC,YAAY,EAAE,SAAS;EACvBC,iBAAiB,EAAE,cAAc;EACjCC,iBAAiB,EAAE,gBAAgB;EACnCC,mBAAmB,EAAE,4BAA4B;EACjDC,yBAAyB,EACvB,0DAA0D;EAC5DC,WAAW,EAAE,UAAU;EACvBC,MAAM,EAAE,SAAS;EACjBC,oBAAoB,EAAE,qDAAqD;EAC3EC,gBAAgB,EAAE,aAAa;EAC/BC,WAAW,EAAE;AACf,CAAC;;AAED;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASC,UAAUA,CAACC,MAAyB,EAAmB;EAC9D,MAAM;IACJC,IAAI;IACJC,QAAQ,GAAG,EAAE;IACbC,cAAc,GAAG,EAAE;IACnBC,MAAM,GAAGrB,cAAc;IACvBsB;EACF,CAAC,GAAGL,MAAM;EAEV,MAAMM,eAA8C,GAAGD,SAAS,GAC5D;IAAE,GAAGrB,iBAAiB;IAAE,GAAGqB;EAAU,CAAC,GACtCrB,iBAAiB;EAErB,OAAOF,mBAAmB,CAACyB,IAAI,CAAC;IAC9BN,IAAI;IACJG,MAAM;IACND,cAAc;IACdD,QAAQ;IACRG,SAAS,EAAEC;EACb,CAAC,CAAC;AACJ;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAME,WAAW,CAAC;EAChB;AACF;AACA;AACA;AACA;EACE,OAAOC,IAAIA,CAACT,MAAyB,EAAQ;IAC3CD,UAAU,CAACC,MAAM,CAAC,CAACU,IAAI,CAACV,MAAM,CAACW,MAAM,CAAC,CAACC,KAAK,CAAC,MAAMZ,MAAM,CAACa,QAAQ,GAAG,CAAC,CAAC;EACzE;;EAEA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACE,OAAON,IAAIA,CACTN,IAAY,EACZa,OAAiE,EAChD;IACjB,OAAOf,UAAU,CAAC;MAAE,GAAGe,OAAO;MAAEb;IAAK,CAAC,CAAC;EACzC;;EAEA;AACF;AACA;EACE,OAAOc,IAAIA,CAACf,MAAyB,EAAQ;IAC3CQ,WAAW,CAACC,IAAI,CAACT,MAAM,CAAC;EAC1B;AACF;;AAEA;;AAEA;AACA;AACA;AACA,MAAMgB,WAAW,GAAGR,WAAW;AAE/B,SAASA,WAAW,EAAEQ,WAAW;AACjC,eAAeR,WAAW;;AAE1B;;AAEA","ignoreList":[]}
@@ -0,0 +1,46 @@
1
+ import type { TurboModule } from 'react-native';
2
+ /**
3
+ * `UnsafeObject` is the codegen-recognised passthrough type for an untyped JS
4
+ * object parameter. The React Native codegen AST parser matches on the name
5
+ * "UnsafeObject" in the source and maps it to NSDictionary* (iOS) /
6
+ * ReadableMap (Android).
7
+ *
8
+ * It must be declared as an empty object type `{}` — NOT as `Record<string, any>`,
9
+ * which the codegen parser rejects with "Unrecognised generic type 'Record'".
10
+ * The tsc compiler accepts `{}` fine for this purpose.
11
+ */
12
+ type UnsafeObject = {};
13
+ /**
14
+ * TurboModule codegen spec for RNPhotoEditor.
15
+ *
16
+ * Design notes
17
+ * ────────────
18
+ * • `props` is typed as `UnsafeObject` — the correct codegen-recognised alias
19
+ * for an untyped JS object. Using plain `Object` is rejected by the strict
20
+ * codegen validator in React Native 0.74+.
21
+ *
22
+ * • The method returns `Promise<string>` instead of accepting two `Callback`
23
+ * parameters. `Callback` parameters are unsafe on New Architecture because
24
+ * they are backed by a `CallbackHolder` tied to the current JS context; if
25
+ * the JS context reloads while the native Activity / ViewController is open
26
+ * (Fast Refresh, error boundary recovery) the stored block/lambda becomes
27
+ * dangling. A `Promise` is resolved or rejected by the native side exactly
28
+ * once and is safe across context reloads.
29
+ *
30
+ * • On Old Architecture `TurboModuleRegistry.getEnforcing` falls through to
31
+ * the `NativeModules` bridge automatically (RN ≥ 0.73), so no separate
32
+ * bridge registration is needed.
33
+ */
34
+ export interface Spec extends TurboModule {
35
+ /**
36
+ * Open the native photo editor.
37
+ *
38
+ * @param props - Editor configuration object (path, colors, stickers, …).
39
+ * @returns Promise that resolves with the saved image path, or rejects with
40
+ * code "CANCELLED" when the user dismisses without saving.
41
+ */
42
+ edit(props: UnsafeObject): Promise<string>;
43
+ }
44
+ declare const _default: Spec;
45
+ export default _default;
46
+ //# sourceMappingURL=NativeRNPhotoEditor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NativeRNPhotoEditor.d.ts","sourceRoot":"","sources":["../../src/NativeRNPhotoEditor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD;;;;;;;;;GASG;AAEH,KAAK,YAAY,GAAG,EAAE,CAAC;AAEvB;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC;;;;;;OAMG;IACH,IAAI,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC5C;;AAED,wBAAuE"}
@@ -1,5 +1,6 @@
1
1
  /**
2
2
  * Localization strings for the image editor UI.
3
+ * All fields are optional — unset keys fall back to the English defaults.
3
4
  */
4
5
  export interface ImageEditorLanguage {
5
6
  /** Title for the "Done" button */
@@ -31,89 +32,98 @@ export interface ImageEditorLanguage {
31
32
  /** Title for the "Eraser" tool */
32
33
  eraserTitle?: string;
33
34
  }
34
- /** Editor control types that can be shown or hidden. */
35
+ /**
36
+ * Editor control identifiers that can be hidden via `hiddenControls`.
37
+ */
35
38
  export type EditorControl = 'text' | 'clear' | 'draw' | 'save' | 'share' | 'sticker' | 'crop';
36
39
  /**
37
40
  * Configuration options for the image editor.
38
41
  */
39
42
  export interface ImageEditorConfig {
40
- /** Path to the image file to edit (required). */
43
+ /**
44
+ * Local file path (or file:// URI) of the image to edit.
45
+ * The editor overwrites this file when the user taps Done.
46
+ */
41
47
  path: string;
42
48
  /**
43
- * Array of hex color strings available for drawing and text.
44
- * @default ['#000000', '#808080', '#a9a9a9', '#FFFFFE', '#0000ff', '#00ff00', '#ff0000', '#ffff00', '#ffa500', '#800080', '#00ffff', '#a52a2a', '#ff00ff']
49
+ * Hex color strings for the drawing and text colour picker.
50
+ * Accepts #RGB, #RRGGBB, and #AARRGGBB formats.
51
+ * @default DEFAULT_COLORS (13-colour palette)
45
52
  */
46
53
  colors?: string[];
47
54
  /**
48
- * Array of sticker image names to show in the sticker picker.
49
- * Images must be added to native project resources.
50
- * - iOS: Add to Resources folder
51
- * - Android: Add to drawable folder
55
+ * Sticker image names from native resources.
56
+ * iOS: main bundle image names. Android: res/drawable/ file names (no extension).
52
57
  * @default []
53
58
  */
54
59
  stickers?: string[];
55
60
  /**
56
- * Array of editor controls to hide.
61
+ * Controls to remove from the editor toolbar.
57
62
  * @default []
58
63
  */
59
64
  hiddenControls?: EditorControl[];
60
65
  /**
61
- * Localization strings for the editor UI.
66
+ * Localization overrides for editor UI strings.
67
+ * Unset keys fall back to English defaults.
62
68
  */
63
69
  languages?: ImageEditorLanguage;
64
70
  /**
65
- * Callback invoked when editing is complete.
66
- * @param imagePath - The path to the edited image file.
71
+ * Called when the user saves the edited image.
72
+ * `imagePath` is the local path to the overwritten file.
73
+ * Only used by `ImageEditor.open()` — ignored by `ImageEditor.edit()`.
67
74
  */
68
75
  onDone?: (imagePath: string) => void;
69
76
  /**
70
- * Callback invoked when editing is cancelled.
71
- * @param resultCode - The native result code.
77
+ * Called when the user dismisses without saving.
78
+ * Only used by `ImageEditor.open()` — ignored by `ImageEditor.edit()`.
72
79
  */
73
- onCancel?: (resultCode: number) => void;
80
+ onCancel?: () => void;
74
81
  }
75
82
  /**
76
- * React Native Image Editor - Native photo editing bridge for iOS and Android.
83
+ * React Native Image Editor — native photo editing for iOS and Android.
84
+ *
85
+ * Supports the New Architecture (Fabric + TurboModules) and the classic bridge.
77
86
  *
78
87
  * @example
79
88
  * ```ts
80
- * import { ImageEditor } from '@phucprime/react-native-image-editor';
81
- *
82
- * // Callback-based usage
83
- * ImageEditor.open({
84
- * path: '/path/to/image.jpg',
85
- * onDone: (editedPath) => console.log('Edited:', editedPath),
86
- * onCancel: () => console.log('Cancelled'),
89
+ * // Promise / async-await (recommended)
90
+ * const saved = await ImageEditor.edit('/path/to/photo.jpg', {
91
+ * colors: ['#ff0000', '#00ff00', '#0000ff'],
92
+ * stickers: ['heart', 'star'],
87
93
  * });
88
94
  *
89
- * // Promise-based usage
90
- * const editedPath = await ImageEditor.edit('/path/to/image.jpg', {
91
- * colors: ['#ff0000', '#00ff00', '#0000ff'],
95
+ * // Callback
96
+ * ImageEditor.open({
97
+ * path: '/path/to/photo.jpg',
98
+ * onDone: (path) => console.log('saved:', path),
99
+ * onCancel: () => console.log('cancelled'),
92
100
  * });
93
101
  * ```
94
102
  */
95
103
  declare class ImageEditor {
96
104
  /**
97
- * Open the image editor with callback-based API.
105
+ * Edit an image and receive the result via callbacks.
98
106
  *
99
- * @param config - Editor configuration options.
107
+ * @param config - Editor configuration including `onDone` / `onCancel`.
100
108
  */
101
109
  static open(config: ImageEditorConfig): void;
102
110
  /**
103
- * Edit an image and return a promise with the edited image path.
111
+ * Edit an image and return a Promise.
112
+ *
113
+ * Resolves with the saved image path.
114
+ * Rejects with `{ code: 'CANCELLED' }` when the user dismisses.
104
115
  *
105
- * @param path - Path to the image file to edit.
106
- * @param options - Optional editor configuration (excluding path, onDone, onCancel).
107
- * @returns Promise that resolves with the edited image path, or rejects if cancelled.
116
+ * @param path - Local file path of the image to edit.
117
+ * @param options - Optional editor configuration (excludes path, onDone, onCancel).
108
118
  */
109
119
  static edit(path: string, options?: Omit<ImageEditorConfig, 'path' | 'onDone' | 'onCancel'>): Promise<string>;
110
120
  /**
111
- * @deprecated Use `ImageEditor.open()` instead. This method is kept for backward compatibility.
121
+ * @deprecated Use `ImageEditor.open()` instead.
112
122
  */
113
123
  static Edit(config: ImageEditorConfig): void;
114
124
  }
115
125
  /**
116
- * @deprecated Use `ImageEditor` instead. `PhotoEditor` is an alias kept for backward compatibility.
126
+ * @deprecated Use `ImageEditor` instead.
117
127
  */
118
128
  declare const PhotoEditor: typeof ImageEditor;
119
129
  export { ImageEditor, PhotoEditor };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,kCAAkC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kCAAkC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uCAAuC;IACvC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oCAAoC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qCAAqC;IACrC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kCAAkC;IAClC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,kCAAkC;IAClC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,kDAAkD;IAClD,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,kDAAkD;IAClD,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,sCAAsC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qCAAqC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,6CAA6C;IAC7C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kCAAkC;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,MAAM,aAAa,GACrB,MAAM,GACN,OAAO,GACP,MAAM,GACN,MAAM,GACN,OAAO,GACP,SAAS,GACT,MAAM,CAAC;AAEX;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAElB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAEpB;;;OAGG;IACH,cAAc,CAAC,EAAE,aAAa,EAAE,CAAC;IAEjC;;;OAGG;IACH,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAEhC;;;;OAIG;IACH,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAErC;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AAyED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,cAAM,WAAW;IACf;;;;OAIG;IACH,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI;IAI5C;;;;;;;;OAQG;IACH,MAAM,CAAC,IAAI,CACT,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,IAAI,CAAC,iBAAiB,EAAE,MAAM,GAAG,QAAQ,GAAG,UAAU,CAAC,GAChE,OAAO,CAAC,MAAM,CAAC;IAIlB;;OAEG;IACH,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI;CAG7C;AAID;;GAEG;AACH,QAAA,MAAM,WAAW,oBAAc,CAAC;AAEhC,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC;AACpC,eAAe,WAAW,CAAC;AAE3B,mDAAmD;AACnD,MAAM,MAAM,gBAAgB,GAAG,iBAAiB,CAAC;AACjD,qDAAqD;AACrD,MAAM,MAAM,QAAQ,GAAG,mBAAmB,CAAC"}
package/package.json CHANGED
@@ -1,37 +1,45 @@
1
1
  {
2
2
  "name": "@phucprime/react-native-image-editor",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "React Native: Native Image Editor for iOS and Android with drawing, text, stickers, cropping and more",
5
- "main": "lib/index.js",
6
- "types": "lib/index.d.ts",
7
- "react-native": "src/index",
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",
8
9
  "source": "src/index.ts",
9
10
  "files": [
10
- "src/",
11
- "lib/",
12
- "ios/",
13
- "android/",
14
- "react-native-image-editor.podspec",
15
- "!android/build/",
16
- "!ios/build/",
17
- "!**/__tests__/"
11
+ "src",
12
+ "lib",
13
+ "android/build.gradle",
14
+ "android/gradle",
15
+ "android/gradlew",
16
+ "android/gradlew.bat",
17
+ "android/libs/photo-editor-android.jar",
18
+ "android/src",
19
+ "ios",
20
+ "cpp",
21
+ "app.plugin.js",
22
+ "*.podspec",
23
+ "LICENSE",
24
+ "README.md"
18
25
  ],
19
- "homepage": "https://github.com/phucprime/react-native-image-editor#readme",
26
+ "homepage": "https://github.com/nguyenhoangphucvnm/react-native-image-editor#readme",
20
27
  "repository": {
21
28
  "type": "git",
22
- "url": "git+https://github.com/phucprime/react-native-image-editor.git"
29
+ "url": "git+https://github.com/nguyenhoangphucvnm/react-native-image-editor.git"
23
30
  },
24
31
  "bugs": {
25
- "url": "https://github.com/phucprime/react-native-image-editor/issues"
32
+ "url": "https://github.com/nguyenhoangphucvnm/react-native-image-editor/issues"
26
33
  },
27
34
  "scripts": {
28
- "build": "tsc --project tsconfig.build.json",
35
+ "build": "bob build",
29
36
  "typecheck": "tsc --noEmit",
30
37
  "lint": "prettier --check src/",
31
38
  "format": "prettier --write src/",
32
39
  "clean": "rm -rf lib/",
33
40
  "prepare": "npm run clean && npm run build",
34
- "release": "npm run prepare && npm publish --access public --registry https://registry.npmjs.org/"
41
+ "release": "npm run prepare && npm publish --access public --registry https://registry.npmjs.org/",
42
+ "release:github": "dotenv -- npm publish"
35
43
  },
36
44
  "keywords": [
37
45
  "react-native",
@@ -57,6 +65,20 @@
57
65
  "javaPackageName": "ui.photoeditor"
58
66
  }
59
67
  },
68
+ "react-native-builder-bob": {
69
+ "source": "src",
70
+ "output": "lib",
71
+ "targets": [
72
+ "commonjs",
73
+ "module",
74
+ [
75
+ "typescript",
76
+ {
77
+ "project": "tsconfig.json"
78
+ }
79
+ ]
80
+ ]
81
+ },
60
82
  "peerDependencies": {
61
83
  "react": ">=18.2.0",
62
84
  "react-native": ">=0.73.0"
@@ -70,12 +92,21 @@
70
92
  }
71
93
  },
72
94
  "devDependencies": {
73
- "@types/react": "^18.2.0 || ^19.0.0",
74
- "prettier": "^3.2.0",
95
+ "@types/react": "18.2.0 || 19.0.0",
96
+ "dotenv-cli": "11.0.0",
97
+ "prettier": "3.2.0",
98
+ "react": "19.0.0",
75
99
  "react-native": "0.78.2",
76
- "typescript": "^5.3.0"
100
+ "react-native-builder-bob": "0.43.1",
101
+ "typescript": "5.9.3"
77
102
  },
78
103
  "engines": {
79
104
  "node": ">=16.0.0"
80
- }
81
- }
105
+ },
106
+ "publishConfig": {
107
+ "registry": "https://npm.pkg.github.com"
108
+ },
109
+ "workspaces": [
110
+ "Example"
111
+ ]
112
+ }
@@ -15,6 +15,14 @@ Pod::Spec.new do |s|
15
15
  s.source_files = "ios/**/*.{h,m,mm,swift}"
16
16
  s.dependency "iOSPhotoEditor"
17
17
 
18
+ # Always enforce C++17 so that C++ standard-library headers (<utility>, <vector>,
19
+ # <chrono>, …) resolve correctly when the pod is compiled alongside React Native's
20
+ # C++ TurboModule/JSI headers, regardless of architecture or RN version.
21
+ s.pod_target_xcconfig = {
22
+ "CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
23
+ "OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
24
+ }
25
+
18
26
  # Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0.
19
27
  if respond_to?(:install_modules_dependencies, true)
20
28
  install_modules_dependencies(s)
@@ -24,11 +32,6 @@ Pod::Spec.new do |s|
24
32
  # Don't install the dependencies when we run `pod install` in the old architecture.
25
33
  if ENV["RCT_NEW_ARCH_ENABLED"] == "1"
26
34
  s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
27
- s.pod_target_xcconfig = {
28
- "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
29
- "OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
30
- "CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
31
- }
32
35
  s.dependency "React-Codegen"
33
36
  s.dependency "RCT-Folly"
34
37
  s.dependency "RCTRequired"
@@ -1,19 +1,49 @@
1
1
  import type { TurboModule } from 'react-native';
2
2
  import { TurboModuleRegistry } from 'react-native';
3
3
 
4
+ /**
5
+ * `UnsafeObject` is the codegen-recognised passthrough type for an untyped JS
6
+ * object parameter. The React Native codegen AST parser matches on the name
7
+ * "UnsafeObject" in the source and maps it to NSDictionary* (iOS) /
8
+ * ReadableMap (Android).
9
+ *
10
+ * It must be declared as an empty object type `{}` — NOT as `Record<string, any>`,
11
+ * which the codegen parser rejects with "Unrecognised generic type 'Record'".
12
+ * The tsc compiler accepts `{}` fine for this purpose.
13
+ */
14
+ // eslint-disable-next-line @typescript-eslint/ban-types
15
+ type UnsafeObject = {};
16
+
4
17
  /**
5
18
  * TurboModule codegen spec for RNPhotoEditor.
6
19
  *
7
- * This spec enables proper New Architecture (Fabric + TurboModules) support
8
- * with compile-time type validation. On Old Architecture, TurboModuleRegistry
9
- * falls back to the NativeModules bridge automatically.
20
+ * Design notes
21
+ * ────────────
22
+ * • `props` is typed as `UnsafeObject` — the correct codegen-recognised alias
23
+ * for an untyped JS object. Using plain `Object` is rejected by the strict
24
+ * codegen validator in React Native 0.74+.
25
+ *
26
+ * • The method returns `Promise<string>` instead of accepting two `Callback`
27
+ * parameters. `Callback` parameters are unsafe on New Architecture because
28
+ * they are backed by a `CallbackHolder` tied to the current JS context; if
29
+ * the JS context reloads while the native Activity / ViewController is open
30
+ * (Fast Refresh, error boundary recovery) the stored block/lambda becomes
31
+ * dangling. A `Promise` is resolved or rejected by the native side exactly
32
+ * once and is safe across context reloads.
33
+ *
34
+ * • On Old Architecture `TurboModuleRegistry.getEnforcing` falls through to
35
+ * the `NativeModules` bridge automatically (RN ≥ 0.73), so no separate
36
+ * bridge registration is needed.
10
37
  */
11
38
  export interface Spec extends TurboModule {
12
- Edit(
13
- props: Object,
14
- onDone: (result: string) => void,
15
- onCancel: (result: number) => void,
16
- ): void;
39
+ /**
40
+ * Open the native photo editor.
41
+ *
42
+ * @param props - Editor configuration object (path, colors, stickers, …).
43
+ * @returns Promise that resolves with the saved image path, or rejects with
44
+ * code "CANCELLED" when the user dismisses without saving.
45
+ */
46
+ edit(props: UnsafeObject): Promise<string>;
17
47
  }
18
48
 
19
49
  export default TurboModuleRegistry.getEnforcing<Spec>('RNPhotoEditor');