diff --git a/docs-validation/1_introduction/NativeModules.tsx b/docs-validation/1_introduction/NativeModules.tsx index decadec9c..1042f71b9 100644 --- a/docs-validation/1_introduction/NativeModules.tsx +++ b/docs-validation/1_introduction/NativeModules.tsx @@ -21,7 +21,7 @@ import Clipboard from '@react-native-clipboard/clipboard'; import { CameraRoll } from '@react-native-camera-roll/camera-roll'; import RNFBMessaging from '@react-native-firebase/messaging'; import Video from 'react-native-video'; -import * as DocumentPicker from 'react-native-document-picker'; +import * as DocumentPicker from '@react-native-documents/picker'; import * as FileAccess from 'react-native-file-access'; import * as ImagePicker from 'react-native-image-picker'; import * as Permissions from 'react-native-permissions'; diff --git a/docs-validation/1_introduction/SendYourFirstMessage.tsx b/docs-validation/1_introduction/SendYourFirstMessage.tsx index 87c8a204f..bb849c389 100644 --- a/docs-validation/1_introduction/SendYourFirstMessage.tsx +++ b/docs-validation/1_introduction/SendYourFirstMessage.tsx @@ -18,7 +18,7 @@ import Clipboard from '@react-native-clipboard/clipboard'; import { CameraRoll } from '@react-native-camera-roll/camera-roll'; import RNFBMessaging from '@react-native-firebase/messaging'; import Video from 'react-native-video'; -import * as DocumentPicker from 'react-native-document-picker'; +import * as DocumentPicker from '@react-native-documents/picker'; import * as FileAccess from 'react-native-file-access'; import * as ImagePicker from 'react-native-image-picker'; import * as Permissions from 'react-native-permissions'; diff --git a/docs-validation/package.json b/docs-validation/package.json index 36c2452c7..5a24a35a4 100644 --- a/docs-validation/package.json +++ b/docs-validation/package.json @@ -11,6 +11,7 @@ "@bam.tech/react-native-image-resizer": "^3.0.10", "@react-native-camera-roll/camera-roll": "^7.8.1", "@react-native-clipboard/clipboard": "^1.14.1", + "@react-native-documents/picker": "^10.1.0", "@react-native-firebase/messaging": "^14.7.0", "@react-navigation/native": "^6.1.17", "@react-navigation/native-stack": "^6.10.0", @@ -20,7 +21,6 @@ "react-native": "0.74.3", "react-native-audio-recorder-player": "^3.6.10", "react-native-create-thumbnail": "^2.0.0", - "react-native-document-picker": "^9.3.0", "react-native-file-access": "^3.1.0", "react-native-image-picker": "^7.1.2", "react-native-mmkv": "^2.12.2", diff --git a/packages/uikit-react-native/README.md b/packages/uikit-react-native/README.md index 26b3a953e..354ce63fe 100644 --- a/packages/uikit-react-native/README.md +++ b/packages/uikit-react-native/README.md @@ -165,7 +165,7 @@ import Clipboard from '@react-native-clipboard/clipboard'; import { CameraRoll } from '@react-native-camera-roll/camera-roll'; import RNFBMessaging from '@react-native-firebase/messaging'; import Video from 'react-native-video'; -import * as DocumentPicker from 'react-native-document-picker'; +import * as DocumentPicker from '@react-native-documents/picker'; import * as FileAccess from 'react-native-file-access'; import * as ImagePicker from 'react-native-image-picker'; import * as Permissions from 'react-native-permissions'; diff --git a/packages/uikit-react-native/package.json b/packages/uikit-react-native/package.json index 9bdf8dd8e..0f592e385 100644 --- a/packages/uikit-react-native/package.json +++ b/packages/uikit-react-native/package.json @@ -71,6 +71,7 @@ "@react-native-camera-roll/camera-roll": "^7.8.1", "@react-native-clipboard/clipboard": "^1.14.1", "@react-native-community/netinfo": "^11.3.2", + "@react-native-documents/picker": "^10.0.0", "@react-native-firebase/app": "^14.4.0", "@react-native-firebase/messaging": "^14.4.0", "@types/react": "*", @@ -108,6 +109,7 @@ "@react-native-camera-roll/camera-roll": ">=5.0.0", "@react-native-clipboard/clipboard": ">=1.8.5", "@react-native-community/netinfo": ">=9.3.0", + "@react-native-documents/picker": ">=10.0.0", "@react-native-firebase/messaging": ">=14.4.0", "@sendbird/chat": "^4.16.0", "@sendbird/react-native-scrollview-enhancer": "*", @@ -145,6 +147,9 @@ "@react-native-clipboard/clipboard": { "optional": true }, + "@react-native-documents/picker": { + "optional": true + }, "@react-native-firebase/messaging": { "optional": true }, diff --git a/packages/uikit-react-native/src/platform/createFileService.native.ts b/packages/uikit-react-native/src/platform/createFileService.native.ts index 28ec7adf7..37841da35 100644 --- a/packages/uikit-react-native/src/platform/createFileService.native.ts +++ b/packages/uikit-react-native/src/platform/createFileService.native.ts @@ -1,6 +1,5 @@ import type { CameraRoll } from '@react-native-camera-roll/camera-roll'; import { Platform } from 'react-native'; -import type * as DocumentPicker from 'react-native-document-picker'; import type * as FileAccess from 'react-native-file-access'; import type * as ImagePicker from 'react-native-image-picker'; import type * as Permissions from 'react-native-permissions'; @@ -18,6 +17,7 @@ import { import SBUError from '../libs/SBUError'; import nativePermissionGranted from '../utils/nativePermissionGranted'; import normalizeFile from '../utils/normalizeFile'; +import { DocumentPicker, openDocument } from './openDocument.native'; import type { FilePickerResponse, FileServiceInterface, @@ -52,7 +52,7 @@ const createNativeFileService = ({ fsModule, }: { imagePickerModule: typeof ImagePicker; - documentPickerModule: typeof DocumentPicker; + documentPickerModule: DocumentPicker; permissionModule: typeof Permissions; mediaLibraryModule: typeof CameraRoll; fsModule: typeof FileAccess; @@ -78,6 +78,7 @@ const createNativeFileService = ({ const status = await permissionModule.checkMultiple(requiredPermissions); return nativePermissionGranted(status); } + async requestCameraPermission(): Promise { const requiredPermissionsStatus = await permissionModule.requestMultiple(requiredPermissions); if (!nativePermissionGranted(requiredPermissionsStatus)) return false; @@ -85,10 +86,12 @@ const createNativeFileService = ({ await permissionModule.requestMultiple(optionalPermissions); return true; } + async hasMediaLibraryPermission(): Promise { const status = await permissionModule.checkMultiple(mediaLibraryPermissions); return nativePermissionGranted(status); } + async requestMediaLibraryPermission(): Promise { const status = await permissionModule.requestMultiple(mediaLibraryPermissions); return nativePermissionGranted(status); @@ -129,6 +132,7 @@ const createNativeFileService = ({ const { fileName: name, fileSize: size, type, uri } = response.assets?.[0] ?? {}; return normalizeFile({ uri, size, name, type }); } + async openMediaLibrary(options?: OpenMediaLibraryOptions): Promise { /** * NOTE: options.selectionLimit {@link https://github.com/react-native-image-picker/react-native-image-picker#options} @@ -172,17 +176,11 @@ const createNativeFileService = ({ .map(({ fileName: name, fileSize: size, type, uri }) => normalizeFile({ uri, size, name, type })), ); } + async openDocument(options?: OpenDocumentOptions): Promise { - try { - const { uri, size, name, type } = await documentPickerModule.pickSingle(); - return normalizeFile({ uri, size, name, type }); - } catch (e) { - if (!documentPickerModule.isCancel(e) && documentPickerModule.isInProgress(e)) { - options?.onOpenFailure?.(SBUError.UNKNOWN, e); - } - return null; - } + return await openDocument(documentPickerModule, options); } + async save(options: SaveOptions): Promise { const hasPermission = await this.hasMediaLibraryPermission(); if (!hasPermission) { diff --git a/packages/uikit-react-native/src/platform/openDocument.native.ts b/packages/uikit-react-native/src/platform/openDocument.native.ts new file mode 100644 index 000000000..9167e174b --- /dev/null +++ b/packages/uikit-react-native/src/platform/openDocument.native.ts @@ -0,0 +1,59 @@ +import type * as NewDocumentsPicker from '@react-native-documents/picker'; +import type * as OldDocumentPicker from 'react-native-document-picker'; + +import { Logger } from '@sendbird/uikit-utils'; + +import SBUError from '../libs/SBUError'; +import normalizeFile from '../utils/normalizeFile'; +import type { FilePickerResponse, OpenDocumentOptions } from './types'; + +export type DocumentPicker = typeof OldDocumentPicker | typeof NewDocumentsPicker; + +async function openDocumentByOldDocumentPicker( + documentPickerModule: typeof OldDocumentPicker, + options?: OpenDocumentOptions, +): Promise { + Logger.warn('please update to @react-native-documents/picker'); + try { + const { uri, size, name, type } = await documentPickerModule.pickSingle(); + return normalizeFile({ uri, size, name, type }); + } catch (e) { + if (!documentPickerModule.isCancel(e) && documentPickerModule.isInProgress(e)) { + options?.onOpenFailure?.(SBUError.UNKNOWN, e); + } + return null; + } +} + +async function openDocumentByNewDocumentsPicker( + documentPickerModule: typeof NewDocumentsPicker, + options?: OpenDocumentOptions, +): Promise { + try { + const results = await documentPickerModule.pick(); + const { uri, size, name, type } = results[0]; + return normalizeFile({ uri, size, name, type }); + } catch (e) { + if ( + !documentPickerModule.isErrorWithCode(documentPickerModule.errorCodes.OPERATION_CANCELED) && + documentPickerModule.isErrorWithCode(documentPickerModule.errorCodes.IN_PROGRESS) + ) { + options?.onOpenFailure?.(SBUError.UNKNOWN, e); + } + return null; + } +} + +function isOldModule(documentPicker: DocumentPicker): documentPicker is typeof OldDocumentPicker { + return 'pickSingle' in documentPicker && typeof documentPicker.pickSingle === 'function'; +} + +export async function openDocument( + documentPickerModule: DocumentPicker, + options?: OpenDocumentOptions, +): Promise { + if (isOldModule(documentPickerModule)) { + return await openDocumentByOldDocumentPicker(documentPickerModule, options); + } + return await openDocumentByNewDocumentsPicker(documentPickerModule, options); +} diff --git a/sample/ios/Podfile b/sample/ios/Podfile index ad198988f..fff367e5a 100644 --- a/sample/ios/Podfile +++ b/sample/ios/Podfile @@ -6,7 +6,9 @@ require Pod::Executable.execute_command('node', ['-p', {paths: [process.argv[1]]}, )', __dir__]).strip -platform :ios, min_ios_version_supported +# Since the minimum supported version of @react-native-documents/picker is iOS 14. +platform :ios, 14 +# platform :ios, min_ios_version_supported prepare_react_native_project! linkage = ENV['USE_FRAMEWORKS'] diff --git a/sample/ios/Podfile.lock b/sample/ios/Podfile.lock index c3691710f..3491c4ee9 100644 --- a/sample/ios/Podfile.lock +++ b/sample/ios/Podfile.lock @@ -1044,7 +1044,7 @@ PODS: - Yoga - react-native-create-thumbnail (2.0.0): - React-Core - - react-native-document-picker (9.3.1): + - react-native-document-picker (10.1.2): - DoubleConversion - glog - hermes-engine @@ -1510,7 +1510,7 @@ DEPENDENCIES: - React-Mapbuffer (from `../../node_modules/react-native/ReactCommon`) - "react-native-cameraroll (from `../../node_modules/@react-native-camera-roll/camera-roll`)" - react-native-create-thumbnail (from `../../node_modules/react-native-create-thumbnail`) - - react-native-document-picker (from `../../node_modules/react-native-document-picker`) + - "react-native-document-picker (from `../../node_modules/@react-native-documents/picker`)" - react-native-image-picker (from `../../node_modules/react-native-image-picker`) - "react-native-image-resizer (from `../../node_modules/@bam.tech/react-native-image-resizer`)" - react-native-mmkv (from `../../node_modules/react-native-mmkv`) @@ -1650,7 +1650,7 @@ EXTERNAL SOURCES: react-native-create-thumbnail: :path: "../../node_modules/react-native-create-thumbnail" react-native-document-picker: - :path: "../../node_modules/react-native-document-picker" + :path: "../../node_modules/@react-native-documents/picker" react-native-image-picker: :path: "../../node_modules/react-native-image-picker" react-native-image-resizer: @@ -1763,7 +1763,7 @@ SPEC CHECKSUMS: Permission-PhotoLibrary: 03c52ed95dadfb0f2ba4c7663786cce0c4e0c978 Permission-PhotoLibraryAddOnly: c4fbf91806bbdc3ed877049bc09fbe58ad9a7c97 PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 - RCT-Folly: 5dc73daec3476616d19e8a53f0156176f7b55461 + RCT-Folly: 02617c592a293bd6d418e0a88ff4ee1f88329b47 RCTDeprecation: 4c7eeb42be0b2e95195563c49be08d0b839d22b4 RCTRequired: d530a0f489699c8500e944fde963102c42dcd0c2 RCTTypeSafety: b20878506b094fa3d9007d7b9e4be0faa3562499 @@ -1789,7 +1789,7 @@ SPEC CHECKSUMS: React-Mapbuffer: 9f68550e7c6839d01411ac8896aea5c868eff63a react-native-cameraroll: 4f313ab09aeaf42ac5f72dec840641da7656f104 react-native-create-thumbnail: ab55d24aea01723cf386f18b0b542aabb1982f27 - react-native-document-picker: c4f197741c327270453aa9840932098e0064fd52 + react-native-document-picker: 570a73e1d3a71d2b34e1c7d7d46c7f2e3c14b0cd react-native-image-picker: c3afe5472ef870d98a4b28415fc0b928161ee5f7 react-native-image-resizer: fd0c333eca55147bd55c5e054cac95dcd0da6814 react-native-mmkv: 8c9a677e64a1ac89b0c6cf240feea528318b3074 @@ -1839,6 +1839,6 @@ SPEC CHECKSUMS: Yoga: 04f1db30bb810187397fa4c37dd1868a27af229c ZIPFoundation: b8c29ea7ae353b309bc810586181fd073cb3312c -PODFILE CHECKSUM: 854e85b2bbfd7d0e442b6dea393d8c15cb83909e +PODFILE CHECKSUM: a7dd46320c0e4bc28bcdaa9f6fbf4caf6e4131d4 COCOAPODS: 1.15.2 diff --git a/sample/package.json b/sample/package.json index c351170cf..1f19f02c5 100644 --- a/sample/package.json +++ b/sample/package.json @@ -23,6 +23,7 @@ "@react-native-community/netinfo": "^11.3.2", "@react-native-community/push-notification-ios": "^1.11.0", "@react-native-community/slider": "^4.2.0", + "@react-native-documents/picker": "^10.1.0", "@react-native-firebase/app": "^14.7.0", "@react-native-firebase/messaging": "^14.7.0", "@react-navigation/bottom-tabs": "^6.6.0", @@ -41,7 +42,6 @@ "react-native": "0.74.3", "react-native-audio-recorder-player": "^3.6.10", "react-native-create-thumbnail": "^2.0.0", - "react-native-document-picker": "^9.3.0", "react-native-fast-image": "^8.6.3", "react-native-file-access": "^3.1.0", "react-native-image-picker": "^7.1.2", diff --git a/sample/src/factory/index.ts b/sample/src/factory/index.ts index b44f1dc24..214930351 100644 --- a/sample/src/factory/index.ts +++ b/sample/src/factory/index.ts @@ -1,12 +1,12 @@ import * as ImageResizer from '@bam.tech/react-native-image-resizer'; import { CameraRoll } from '@react-native-camera-roll/camera-roll'; import Clipboard from '@react-native-clipboard/clipboard'; +import * as DocumentPicker from '@react-native-documents/picker'; import RNFBMessaging from '@react-native-firebase/messaging'; import { createNativeStackNavigator } from '@react-navigation/native-stack'; import { Platform, StatusBar } from 'react-native'; import * as AudioRecorderPlayer from 'react-native-audio-recorder-player'; import * as CreateThumbnail from 'react-native-create-thumbnail'; -import * as DocumentPicker from 'react-native-document-picker'; import * as FileAccess from 'react-native-file-access'; import * as ImagePicker from 'react-native-image-picker'; import * as Permissions from 'react-native-permissions'; diff --git a/yarn.lock b/yarn.lock index 8ec386fbd..bffe67297 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1237,7 +1237,7 @@ "@babel/parser" "^7.25.9" "@babel/types" "^7.25.9" -"@babel/traverse--for-generate-function-map@npm:@babel/traverse@^7.25.3", "@babel/traverse@^7.1.0", "@babel/traverse@^7.13.0", "@babel/traverse@^7.20.0", "@babel/traverse@^7.25.3", "@babel/traverse@^7.25.9", "@babel/traverse@^7.7.0", "@babel/traverse@^7.7.4": +"@babel/traverse--for-generate-function-map@npm:@babel/traverse@^7.25.3": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.25.9.tgz#a50f8fe49e7f69f53de5bea7e413cd35c5e13c84" integrity sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw== @@ -1266,6 +1266,19 @@ debug "^4.1.0" globals "^11.1.0" +"@babel/traverse@^7.1.0", "@babel/traverse@^7.13.0", "@babel/traverse@^7.20.0", "@babel/traverse@^7.25.3", "@babel/traverse@^7.25.9", "@babel/traverse@^7.7.0", "@babel/traverse@^7.7.4": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.25.9.tgz#a50f8fe49e7f69f53de5bea7e413cd35c5e13c84" + integrity sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw== + dependencies: + "@babel/code-frame" "^7.25.9" + "@babel/generator" "^7.25.9" + "@babel/parser" "^7.25.9" + "@babel/template" "^7.25.9" + "@babel/types" "^7.25.9" + debug "^4.3.1" + globals "^11.1.0" + "@babel/types@7.17.0": version "7.17.0" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.17.0.tgz#a826e368bccb6b3d84acd76acad5c0d87342390b" @@ -3280,6 +3293,11 @@ resolved "https://registry.yarnpkg.com/@react-native-community/slider/-/slider-4.5.5.tgz#d70fc5870477760033769bbd6625d57e7d7678b2" integrity sha512-x2N415pg4ZxIltArOKczPwn7JEYh+1OxQ4+hTnafomnMsqs65HZuEWcX+Ch8c5r8V83DiunuQUf5hWGWlw8hQQ== +"@react-native-documents/picker@^10.0.0": + version "10.1.2" + resolved "https://registry.yarnpkg.com/@react-native-documents/picker/-/picker-10.1.2.tgz#2ebbf1eccc7e9efa3690e35ab5f0a811411a57b8" + integrity sha512-JzbFmFp0SmG0FEKt4Q62trewHMFpas2zAX0n5EANwrU9kondnzAEF7/xxz2EA2tfZNwnkHelqG8A7iedGleMRw== + "@react-native-firebase/app@^14.4.0", "@react-native-firebase/app@^14.7.0": version "14.12.0" resolved "https://registry.yarnpkg.com/@react-native-firebase/app/-/app-14.12.0.tgz#d9706973489485d8705ce8344e3b255115b381a8" @@ -15062,7 +15080,16 @@ string-natural-compare@^3.0.1: resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4" integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw== -"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -15168,7 +15195,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -15182,6 +15209,13 @@ strip-ansi@^5.0.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -16374,7 +16408,7 @@ worker-farm@^1.7.0: dependencies: errno "~0.1.7" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -16392,6 +16426,15 @@ wrap-ansi@^6.0.1, wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"