{"_id":"@bingtang-rn/react-native-customized-image-picker","_rev":"2-8bcca621b591b7c29afd56cb93a0d5b9","name":"@bingtang-rn/react-native-customized-image-picker","dist-tags":{"latest":"1.0.1"},"versions":{"1.0.0":{"name":"@bingtang-rn/react-native-customized-image-picker","version":"1.0.0","keywords":["react-native","harmony","harmonyos","react-native-customized-image-picker"],"license":"MIT","_id":"@bingtang-rn/react-native-customized-image-picker@1.0.0","maintainers":[{"name":"luyizouyuan","email":"189605613@qq.com"}],"homepage":"https://gitcode.com/rn_ohos_plugin/react_native_customized_image_picker","dist":{"shasum":"1f046ca34aac59bedb54a6ce044be245e39149f3","tarball":"https://registry.npmjs.org/@bingtang-rn/react-native-customized-image-picker/-/react-native-customized-image-picker-1.0.0.tgz","fileCount":32,"integrity":"sha512-vEbyIBgGBVAbFNonyxYlD/e2+600X5JUfefNV5Qcw7h1G3oUdEnUAY9lbZpqYligbGwRAEHARmEQrNZ3Lclphg==","signatures":[{"sig":"MEQCIC37izhTq8Cf9uw2/nh7Bu7hqucaTiHjX0Cz3QktkdGqAiBAx6wVufjMLsoRQzWMkDKCtsjS1+AMbw0Sl7JkpP5Ofg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":74263},"main":"./src/index.ts","module":"./src/index.ts","engines":{"node":">=18"},"gitHead":"d2c5c2f4499f3fa9fdef6600147f65a0cf0ab44e","harmony":{"alias":"react-native-customized-image-picker","autolinking":{"ohPackageName":"@oh-rn/react-native-customized-image-picker","cppPackageClassName":"CustomizedImagePickerPackage","etsPackageClassName":"CustomizedImagePickerPackage","cmakeLibraryTargetName":"customized_image_picker"},"codegenConfig":[{"version":1,"specPaths":["./src/specs/v1"]}]},"private":false,"scripts":{"prepare":"echo skip","codegen-lib":"react-native codegen-harmony --cpp-output-path ./harmony/customized_image_picker/src/main/cpp/generated --ets-output-path ./harmony/customized_image_picker/src/main/ets/generated"},"_npmUser":{"name":"luyizouyuan","email":"189605613@qq.com"},"repository":{"url":"https://gitcode.com/rn_ohos_plugin/react_native_customized_image_picker","type":"git"},"_npmVersion":"11.12.1","description":"适配鸿蒙版本，提供react_native_customized_image_picker组件。","directories":{},"_nodeVersion":"24.15.0","react-native":"./src/index.ts","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.6.3","metro":"^0.81.0","react":"18.2.0","typescript":"5.0.4","@types/react":"18.2.79","react-native":"0.72.5","@react-native/typescript-config":"0.79.5","@react-native-oh/react-native-harmony-cli":"^0.77.50"},"peerDependencies":{"react-native":">=0.72"},"_npmOperationalInternal":{"tmp":"tmp/react-native-customized-image-picker_1.0.0_1785999712517_0.33683255471895324","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"_id":"@bingtang-rn/react-native-customized-image-picker@1.0.1","dist":{"shasum":"e8983c9f8d554f2235d761c4c44eb1cf3cd0feb7","tarball":"https://registry.npmjs.org/@bingtang-rn/react-native-customized-image-picker/-/react-native-customized-image-picker-1.0.1.tgz","fileCount":32,"integrity":"sha512-Iy9HboAER8vNcYFBKYnbER264npq6YIyTYcKvEHLYQavmiMtlaV5+bBxmhmT6ktz+W3QdLwn+ekiY6Lxw9du9Q==","signatures":[{"sig":"MEYCIQD6ArW+tRyZ/HkOlUf/bl9yd8Y/RNrGpbXeIC0xFVIgJgIhAPYt7YmOXumV7pVaku/j07WyOKZBqQsRr5iFVTKEhCVr","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQD+o4/o/1ChkrSZ3Waj+BH4w48MlM0XahSkKR1VVqPEHwIhAOWwrWfGr7+3GCgpyYLANcvUO0J2d+Lhf6eiX+BtzN+e"}],"unpackedSize":74112},"main":"./src/index.ts","name":"@bingtang-rn/react-native-customized-image-picker","_from":"file:bingtang-rn-react-native-customized-image-picker-1.0.1.tgz","module":"./src/index.ts","engines":{"node":">=18"},"harmony":{"alias":"react-native-customized-image-picker","autolinking":{"ohPackageName":"@bingtang-rn/react-native-customized-image-picker","cppPackageClassName":"CustomizedImagePickerPackage","etsPackageClassName":"CustomizedImagePickerPackage","cmakeLibraryTargetName":"customized_image_picker"},"codegenConfig":[{"version":1,"specPaths":["./src/specs/v1"]}]},"license":"MIT","private":false,"scripts":{"prepare":"echo skip","codegen-lib":"react-native codegen-harmony --cpp-output-path ./harmony/customized_image_picker/src/main/cpp/generated --ets-output-path ./harmony/customized_image_picker/src/main/ets/generated"},"version":"1.0.1","_npmUser":{"name":"luyizouyuan","email":"189605613@qq.com"},"homepage":"https://gitcode.com/rn_ohos_plugin/react_native_customized_image_picker","keywords":["react-native","harmony","harmonyos","react-native-customized-image-picker"],"_resolved":"D:\\code\\rn\\npm\\batch\\react_native_customized_image_picker\\bingtang-rn-react-native-customized-image-picker-1.0.1.tgz","_integrity":"sha512-Iy9HboAER8vNcYFBKYnbER264npq6YIyTYcKvEHLYQavmiMtlaV5+bBxmhmT6ktz+W3QdLwn+ekiY6Lxw9du9Q==","repository":{"url":"https://gitcode.com/rn_ohos_plugin/react_native_customized_image_picker","type":"git"},"_npmVersion":"11.12.1","description":"适配鸿蒙版本，提供react_native_customized_image_picker组件。","directories":{},"maintainers":[{"name":"luyizouyuan","email":"189605613@qq.com"}],"_nodeVersion":"24.15.0","react-native":"./src/index.ts","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.6.3","metro":"^0.81.0","react":"18.2.0","typescript":"5.0.4","@types/react":"18.2.79","react-native":"0.72.5","@react-native/typescript-config":"0.79.5","@react-native-oh/react-native-harmony-cli":"^0.77.50"},"peerDependencies":{"react-native":">=0.72"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/react-native-customized-image-picker_1.0.1_1790568670324_0.22321555620001643"}}},"time":{"created":"2026-08-06T07:01:52.319Z","modified":"2026-09-28T04:11:10.595Z","1.0.0":"2026-08-06T07:01:52.662Z","1.0.1":"2026-09-28T04:11:10.426Z"},"license":"MIT","homepage":"https://gitcode.com/rn_ohos_plugin/react_native_customized_image_picker","keywords":["react-native","harmony","harmonyos","react-native-customized-image-picker"],"repository":{"url":"https://gitcode.com/rn_ohos_plugin/react_native_customized_image_picker","type":"git"},"description":"适配鸿蒙版本，提供react_native_customized_image_picker组件。","maintainers":[{"name":"luyizouyuan","email":"189605613@qq.com"}],"readme":"# @bingtang-rn/react-native-customized-image-picker for HarmonyOS\r\n\r\n本项目基于 [react-native-customized-image-picker](https://github.com/liukefu2050/react-native-customized-image-picker) 开发，为 React Native 鸿蒙（OpenHarmony）适配版本。如果在使用过程中有任何问题，可以在GitCode提Issue，会及时跟进。issue地址：[issues](https://gitcode.com/rn_ohos_plugin/react_native_customized_image_picker/issues)。\r\n\r\n## 版本对应关系\r\n\r\n| 鸿蒙适配包版本 | 原始库版本 | 支持 RN 版本 | Autolink | 编译 API 版本 |\r\n| ------------ | ---------- | ------------ | -------- | ------------- |\r\n| 见发布记录 | 1.3.4 | 0.72+ | 是/否 | API17+ |\r\n\r\n## 安装\r\n\r\n```bash\r\nnpm install @bingtang-rn/react-native-customized-image-picker\r\n```\r\n\r\n## 使用\r\n\r\n```tsx\r\nimport ImageCropPicker from 'react-native-customized-image-picker';\r\n\r\n// ① 从图库选择图片（单选 + 裁剪 + 压缩）\r\nconst images = await ImageCropPicker.openPicker({\r\n  cropping: true,\r\n  CropW: 300,\r\n  CropH: 300,\r\n  compressQuality: 80,\r\n  multiple: false,\r\n});\r\n\r\n// ② 从图库多选（图+视频混合，附 base64）\r\nconst mixed = await ImageCropPicker.openPicker({\r\n  multiple: true,\r\n  maxSize: 5,\r\n  isSelectBoth: true,\r\n  includeBase64: false,\r\n});\r\n\r\n// ③ 拍照\r\nconst photo = await ImageCropPicker.openCamera({ isVideo: false });\r\n\r\n// ④ 录像（限制 30 秒）\r\nconst video = await ImageCropPicker.openCamera({\r\n  isVideo: true,\r\n  videoMaximumDuration: 30,\r\n});\r\n\r\n// ⑤ 清理本模块产生的临时文件\r\nawait ImageCropPicker.clean();\r\n```\r\n\r\n> import 时使用原库名 `'react-native-customized-image-picker'`，RNOH alias 会自动重定向到鸿蒙包 `@bingtang-rn/react-native-customized-image-picker`，业务代码无需修改。\r\n\r\n**平台差异**：\r\n- HarmonyOS 图库走系统 `PhotoViewPicker`，无法定制 UI（`title`/`spanCount`/`openCameraOnStart` 等选项不生效，已忽略）。\r\n- HarmonyOS 无系统级裁剪 UI，`cropping` 降级为按 `CropW`/`CropH` 或 `aspectRatioX/Y` 自动 ROI 居中裁剪（无交互）；`showCropCircle` 降级为按 `circleCropRadius` 直径做正方形 ROI（不渲染圆形遮罩）。\r\n- `imageLoader`（PICASSO/GLIDE/FRESCO/UNIVERSAL）鸿蒙端统一用 Image 组件 + PixelMap，忽略。\r\n- 视频压缩：原库 `Compression.compressVideo` 即为 TODO 直接 resolve 原路径，鸿蒙端同样不实现转码压缩。\r\n- 视频元数据（`width`/`height`/`duration`）通过 `AVMetadataExtractor` 提取，`duration` 已转换为秒（对齐 iOS `PHAsset.duration`）。\r\n- 取消选择/拍摄统一 reject `{code:'cancel', message:'cancel'}`，与原库 Android/iOS 一致。\r\n\r\n**权限要求**：\r\n- `PhotoViewPicker` 与 `cameraPicker.pick` 均为系统选择器应用，调用方应用无需声明 `ohos.permission.CAMERA` 或存储权限。\r\n- 文件读写/清理均在应用沙箱 `cacheDir` 内，无需额外权限。\r\n\r\n## Link\r\n\r\n| 版本 | 是否支持 Autolink |\r\n|------|------------------|\r\n| 当前版本 | 是/否 |\r\n\r\n如使用版本支持 Autolink 且工程已接入，可跳过手动配置。\r\n\r\n<details>\r\n<summary>Manual Link 配置</summary>\r\n\r\n> **说明**：本模块需要同时在 C++ 侧和 ETS 侧注册 Package。\r\n\r\n### 1. Overrides RN SDK\r\n\r\n在工程根目录 `oh-package.json5` 添加：\r\n\r\n```json\r\n{\r\n  \"overrides\": {\r\n    \"@rnoh/react-native-openharmony\": \"./react_native_openharmony\"\r\n  }\r\n}\r\n```\r\n\r\n### 2. 引入原生端依赖\r\n\r\n打开 `entry/oh-package.json5`，添加：\r\n\r\n```json\r\n\"dependencies\": {\r\n  \"@bingtang-rn/react-native-customized-image-picker\": \"file:../../node_modules/@bingtang-rn/react-native-customized-image-picker/harmony/customized_image_picker.har\"\r\n}\r\n```\r\n\r\n执行 `ohpm install`。\r\n\r\n### 3. 配置 CMakeLists\r\n\r\n打开 `entry/src/main/cpp/CMakeLists.txt`，添加：\r\n\r\n```cmake\r\nset(OH_MODULES \"${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules\")\r\n\r\nadd_subdirectory(\"${OH_MODULES}/@bingtang-rn/react-native-customized-image-picker/src/main/cpp\" ./customized_image_picker)\r\n\r\ntarget_link_libraries(rnoh_app PUBLIC customized_image_picker)\r\n```\r\n\r\n### 4. 注册 Package（C++ 侧）\r\n\r\n打开 `entry/src/main/cpp/PackageProvider.cpp`，添加：\r\n\r\n```cpp\r\n#include \"CustomizedImagePickerPackage.h\"\r\n\r\nstd::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) {\r\n    return {\r\n        std::make_shared<CustomizedImagePickerPackage>(ctx),\r\n    };\r\n}\r\n```\r\n\r\n### 5. 注册 Package（ETS 侧）\r\n\r\n打开 `entry/src/main/ets/RNPackagesFactory.ets`，添加：\r\n\r\n```typescript\r\nimport { CustomizedImagePickerPackage } from '@bingtang-rn/react-native-customized-image-picker/ts';\r\n\r\nexport function createRNPackages(ctx: RNPackageContext): RNPackage[] {\r\n  return [\r\n    new CustomizedImagePickerPackage(ctx),\r\n  ];\r\n}\r\n```\r\n\r\n</details>\r\n\r\n## 属性 / API\r\n\r\n| API | 描述 | 参数 | 返回值 | HarmonyOS 支持 |\r\n|-----|------|------|--------|----------------|\r\n| openPicker | 拉起图库选择图片/视频，支持单/多选、裁剪、压缩、Base64 | Options | Promise<Image[]> | ✅ 完全支持 |\r\n| openCamera | 拉起相机拍照/录像，支持裁剪（仅图片） | Options | Promise<Image[]> | ✅ 完全支持 |\r\n| clean | 清理本模块在沙箱 cacheDir 产生的临时文件目录 | 无 | Promise<void> | ✅ 完全支持 |\r\n\r\n### Options 字段支持矩阵\r\n\r\n| Option | 描述 | HarmonyOS 支持 |\r\n|--------|------|----------------|\r\n| multiple / maxSize | 多选与上限 | ✅ 完全支持（映射 `PhotoSelectOptions.maxSelectNumber`） |\r\n| isVideo / isSelectBoth | 媒体模式 | ✅ 完全支持（映射 `PhotoViewMIMETypes`） |\r\n| cropping / CropW / CropH / aspectRatioX / aspectRatioY | 裁剪 | ⚠️ 部分支持（无交互 UI，按参数自动 ROI 居中裁剪） |\r\n| showCropCircle / circleCropRadius | 圆形裁剪 | ⚠️ 部分支持（降级为按直径正方形 ROI，无圆形遮罩） |\r\n| compressQuality / minCompressSize / width / height | 压缩 | ✅ 完全支持（`ImagePacker.packToFile` + `DecodingOptions.desiredSize`） |\r\n| includeBase64 | Base64 数据 | ✅ 完全支持（`util.Base64Helper`） |\r\n| videoMaximumDuration | 录像最大时长 | ✅ 完全支持（映射 `PickerProfile.videoDuration`） |\r\n| isPlayGif / isGif | GIF 支持 | ✅ 完全支持（HarmonyOS Image 组件原生支持 GIF 动图） |\r\n| title / spanCount / openCameraOnStart / returnAfterShot / multipleShot / isHidePreview / isHideVideoPreview / isCamera | 图库 UI 定制 | ❌ 不支持（系统 `PhotoViewPicker` 不暴露这些 UI 选项） |\r\n| imageLoader | 图片加载库选择 | ❌ 不支持（鸿蒙统一用 Image 组件 + PixelMap） |\r\n| videoQuality | 视频质量档位 | ❌ 不支持（`cameraPicker` 不暴露质量档位字段） |\r\n| isRecordSelected / allowPickingOriginalPhoto / sortAscendingByModificationDate / showSelectedIndex / allowPickingMultipleVideo / allowPickingVideo / allowPickingImage / allowTakeVideo | iOS TZImagePickerController 专属 | ❌ 不支持（iOS 专属，鸿蒙忽略） |\r\n\r\n### 平台差异\r\n\r\n- **图库 UI**：HarmonyOS 走系统 `PhotoViewPicker`，仅支持 `MIMEType` + `maxSelectNumber`，原库的 `title`/`spanCount`/`openCameraOnStart`/`returnAfterShot`/`multipleShot`/`isHidePreview`/`isHideVideoPreview`/`isCamera` 等 UI 细粒度选项无对应语义，已忽略不生效。\r\n- **裁剪**：HarmonyOS 无系统级裁剪 UI，`cropping`/`CropW`/`CropH`/`aspectRatioX`/`aspectRatioY` 降级为按参数自动 ROI 居中裁剪（无交互）；`showCropCircle`/`circleCropRadius` 降级为按直径做正方形 ROI（不渲染圆形遮罩）。\r\n- **视频压缩**：原库 Android `Compression.compressVideo` 为 TODO（直接 resolve 原路径），鸿蒙端保持一致行为，不实现转码压缩。\r\n- **视频元数据**：`width`/`height`/`duration` 通过 `AVMetadataExtractor` 提取，`duration` 单位为秒（对齐 iOS `PHAsset.duration`）。\r\n- **取消语义**：用户取消选择/拍摄统一 reject `{code:'cancel', message:'cancel'}`，与原库 Android/iOS 一致。\r\n\r\n### 未实现/降级功能\r\n\r\n| 项 | 原因 |\r\n|-----|------|\r\n| 图库 UI 细粒度定制（title/spanCount/openCameraOnStart 等） | 系统 `PhotoViewPicker` 不暴露这些 UI 选项 |\r\n| 交互式裁剪页（uCrop/TZImageCropManager） | HarmonyOS 无系统裁剪 UI，自动 ROI 为最接近替代 |\r\n| 圆形裁剪遮罩渲染 | 无系统圆形遮罩 API，降级为正方形 ROI |\r\n| `imageLoader` 选项 | 鸿蒙统一用 Image 组件 + PixelMap，无对应加载库概念 |\r\n| `videoQuality` 视频质量档位 | `cameraPicker` 不暴露质量档位字段 |\r\n| 视频压缩转码 | 原库未实现（TODO），保持对等 |\r\n| iOS 专属选项（isRecordSelected/allowPickingXxx 等） | iOS TZImagePickerController 专属，鸿蒙忽略 |\r\n\r\n### 使用限制\r\n\r\n- 相机/图库均为系统选择器应用，调用方应用无需声明 `ohos.permission.CAMERA` 或存储权限。\r\n- 文件读写/清理在应用沙箱 `cacheDir` 内，无额外权限。\r\n- 返回 `path` 为沙箱 `cacheDir/ImageCropPicker/` 下临时文件绝对路径，需用 `file://` 前缀作为 Image 组件 source。\r\n- 设备需支持 `SystemCapability.Multimedia.Camera.Core`（相机）与 `SystemCapability.FileManagement.PhotoAccessHelper.Core`（图库）。\r\n\r\n## 快速验证（运行 Example）\r\n\r\n### 前置条件\r\n\r\n| 依赖 | 版本要求 |\r\n|------|----------|\r\n| Node.js | >= 18 |\r\n| DevEco Studio | 5.0+ / 6.0+ |\r\n| HarmonyOS SDK | API 17+ |\r\n\r\n### 运行步骤\r\n\r\n**1. 克隆仓库**\r\n\r\n```bash\r\ngit clone <仓库地址>\r\ncd <仓库目录>\r\n```\r\n\r\n**2. 安装依赖并构建**\r\n\r\n```bash\r\nnpm install --legacy-peer-deps\r\nnpm pack           # 生成 tgz 包（会自动触发 prepare 构建 JS 产物）\r\n```\r\n\r\n**3. 进入 example 目录，安装依赖**\r\n\r\n```bash\r\ncd example\r\nnpm install --legacy-peer-deps\r\n```\r\n\r\n**4. 生成 JS Bundle**\r\n\r\n```bash\r\nnpm run dev\r\n```\r\n\r\n产物：`harmony/entry/src/main/resources/rawfile/bundle.harmony.js`\r\n\r\n**5. 用 DevEco Studio 打开鸿蒙工程**\r\n\r\n- 打开 DevEco Studio\r\n- 选择 `example/harmony` 目录\r\n- 等待 Sync 完成\r\n\r\n**6. 编译并运行 HAP**\r\n\r\n在 DevEco Studio 中点击运行按钮，将 HAP 安装到设备/模拟器。\r\n\r\n> **注意**：Example 中已预置插件依赖和 Package 注册，无需手动配置 Link。\r\n\r\n## 约束与限制\r\n\r\n### 兼容性\r\n\r\n- RNOH: 0.72+\r\n- HarmonyOS SDK: API 17+\r\n- DevEco Studio: 5.0+\r\n\r\n## 遗留问题\r\n\r\n无（或列出已知问题）\r\n\r\n## 开源协议\r\n\r\n本项目基于 [MIT License](https://github.com/liukefu2050/react-native-customized-image-picker/blob/master/LICENSE)，详见 [LICENSE](./LICENSE) 文件。\r\n","readmeFilename":"README.md"}