diff --git a/README.md b/README.md index eacd4f1..9f83d5c 100644 --- a/README.md +++ b/README.md @@ -103,14 +103,17 @@ const takePicture = async () => { * [`getPhoto(...)`](#getphoto) -* [`takePhoto(...)`](#takephoto) * [`pickImages(...)`](#pickimages) * [`pickLimitedLibraryPhotos()`](#picklimitedlibraryphotos) * [`getLimitedLibraryPhotos()`](#getlimitedlibraryphotos) * [`checkPermissions()`](#checkpermissions) * [`requestPermissions(...)`](#requestpermissions) +* [`takePhoto(...)`](#takephoto) * [`recordVideo(...)`](#recordvideo) * [`playVideo(...)`](#playvideo) +* [`chooseFromGallery(...)`](#choosefromgallery) +* [`editPhoto(...)`](#editphoto) +* [`editURIPhoto(...)`](#edituriphoto) * [Interfaces](#interfaces) * [Type Aliases](#type-aliases) * [Enums](#enums) @@ -140,26 +143,6 @@ with the camera. -------------------- -### takePhoto(...) - -```typescript -takePhoto(options: ImageOptions) => Promise -``` - -Prompt the user to pick a photo from an album, or take a new photo -with the camera. - -| Param | Type | -| ------------- | ----------------------------------------------------- | -| **`options`** | ImageOptions | - -**Returns:** Promise<Photo> - -**Since:** 1.0.0 - --------------------- - - ### pickImages(...) ```typescript @@ -245,6 +228,25 @@ Request camera and photo album permissions -------------------- +### takePhoto(...) + +```typescript +takePhoto(options: ImageOptions) => Promise +``` + +Prompt the user to take a photo with the camera. + +| Param | Type | +| ------------- | ----------------------------------------------------- | +| **`options`** | ImageOptions | + +**Returns:** Promise<MediaResult> + +**Since:** 2.0.0 + +-------------------- + + ### recordVideo(...) ```typescript @@ -263,12 +265,69 @@ recordVideo(options: RecordVideoOptions) => Promise ### playVideo(...) ```typescript -playVideo(options: { videoURI: string; }) => Promise +playVideo(options: PlayVideoOptions) => Promise +``` + +| Param | Type | +| ------------- | ------------------------------------------------------------- | +| **`options`** | PlayVideoOptions | + +-------------------- + + +### chooseFromGallery(...) + +```typescript +chooseFromGallery(options: GalleryOptions) => Promise +``` + +Allows the user to pick multiple pictures from the photo gallery. + +| Param | Type | +| ------------- | --------------------------------------------------------- | +| **`options`** | GalleryOptions | + +**Returns:** Promise<MediaResults> + +**Since:** 1.2.0 + +-------------------- + + +### editPhoto(...) + +```typescript +editPhoto(options: EditPhotoOptions) => Promise ``` -| Param | Type | -| ------------- | ---------------------------------- | -| **`options`** | { videoURI: string; } | +Returns a string (base64) representing the photo that was edited + +| Param | Type | +| ------------- | ------------------------------------------------------------- | +| **`options`** | EditPhotoOptions | + +**Returns:** Promise<EditPhotoResult> + +**Since:** 2.0.0 + +-------------------- + + +### editURIPhoto(...) + +```typescript +editURIPhoto(options: EditURIPhotoOptions) => Promise +``` + +Returns a MediaResult object with info about the photo that was edited + +| Param | Type | +| ------------- | ------------------------------------------------------------------- | +| **`options`** | EditURIPhotoOptions | + +**Returns:** Promise<MediaResult> + +**Since:** 2.0.0 -------------------- @@ -360,6 +419,7 @@ playVideo(options: { videoURI: string; }) => Promise | -------------- | -------------------- | | **`path`** | string | | **`webPath`** | string | +| **`exif`** | any | | **`duration`** | number | | **`size`** | number | | **`format`** | string | @@ -374,6 +434,61 @@ playVideo(options: { videoURI: string; }) => Promise | **`includeMetadata`** | boolean | +#### PlayVideoOptions + +| Prop | Type | +| -------------- | ------------------- | +| **`videoURI`** | string | + + +#### MediaResults + +| Prop | Type | +| ------------ | -------------------------- | +| **`photos`** | MediaResult[] | + + +#### GalleryOptions + +| Prop | Type | +| ---------------------------- | ----------------------------------------------- | +| **`mediaType`** | MediaType | +| **`allowMultipleSelection`** | boolean | +| **`limit`** | number | +| **`includeMetadata`** | boolean | +| **`allowEdit`** | boolean | +| **`editInApp`** | boolean | +| **`presentationStyle`** | 'fullscreen' \| 'popover' | +| **`quality`** | number | +| **`width`** | number | +| **`height`** | number | +| **`correctOrientation`** | boolean | + + +#### EditPhotoResult + +| Prop | Type | +| ------------------ | ------------------- | +| **`format`** | string | +| **`base64String`** | string | + + +#### EditPhotoOptions + +| Prop | Type | +| ------------ | ------------------- | +| **`base64`** | string | + + +#### EditURIPhotoOptions + +| Prop | Type | +| --------------------- | -------------------- | +| **`uri`** | string | +| **`saveToGallery`** | boolean | +| **`includeMetadata`** | boolean | + + ### Type Aliases @@ -420,4 +535,13 @@ playVideo(options: { videoURI: string; }) => Promise | **`Rear`** | 'REAR' | | **`Front`** | 'FRONT' | + +#### MediaType + +| Members | Value | +| ------------- | -------------- | +| **`picture`** | 0 | +| **`video`** | 1 | +| **`all`** | 2 | + diff --git a/android/build.gradle b/android/build.gradle index 3b83593..127a410 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -9,6 +9,7 @@ ext { } buildscript { + ext.kotlin_version = project.hasProperty("kotlin_version") ? rootProject.ext.kotlin_version : '2.2.20' repositories { google() mavenCentral() @@ -18,6 +19,7 @@ buildscript { } dependencies { classpath 'com.android.tools.build:gradle:8.13.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" if (System.getenv("CAP_PLUGIN_PUBLISH") == "true") { classpath 'io.github.gradle-nexus:publish-plugin:1.3.0' } @@ -25,7 +27,7 @@ buildscript { } apply plugin: 'com.android.library' -apply plugin: 'org.jetbrains.kotlin.android' +apply plugin: 'kotlin-android' if (System.getenv("CAP_PLUGIN_PUBLISH") == "true") { apply plugin: 'io.github.gradle-nexus.publish-plugin' apply from: file('../../scripts/android/publish-root.gradle') @@ -58,9 +60,10 @@ android { publishing { singleVariant("release") } - kotlinOptions { - jvmTarget = '21' - } +} + +kotlin { + jvmToolchain(21) } repositories { @@ -87,4 +90,4 @@ dependencies { androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion" implementation 'com.google.code.gson:gson:2.10.1' implementation project(':gradle-project-test') -} +} \ No newline at end of file diff --git a/android/src/main/java/com/capacitorjs/plugins/camera/CameraPlugin.kt b/android/src/main/java/com/capacitorjs/plugins/camera/CameraPlugin.kt index 0fdf93f..750c609 100644 --- a/android/src/main/java/com/capacitorjs/plugins/camera/CameraPlugin.kt +++ b/android/src/main/java/com/capacitorjs/plugins/camera/CameraPlugin.kt @@ -19,7 +19,7 @@ import com.getcapacitor.annotation.CapacitorPlugin import com.getcapacitor.annotation.Permission import com.getcapacitor.annotation.PermissionCallback import org.json.JSONException - +import io.ionic.libs.ioncameralib.model.IONCAMRMediaType /** * The Camera plugin makes it easy to take a photo or have the user select a photo * from their albums. @@ -61,7 +61,8 @@ class CameraPlugin : Plugin() { private lateinit var legacyFlow: LegacyCameraFlow private lateinit var ionFlow: IonCameraFlow - + private var videoSettings = VideoSettings() + private var gallerySettings = GallerySettings() override fun load() { super.load() @@ -78,12 +79,14 @@ class CameraPlugin : Plugin() { @PluginMethod fun takePhoto(call: PluginCall) { - ionFlow.takePhoto(call) + val settings = getSettings(call) + ionFlow.takePhoto(call, settings) } @PluginMethod fun recordVideo(call: PluginCall) { - ionFlow.recordVideo(call) + videoSettings = getVideoSettings(call) + ionFlow.recordVideo(call, videoSettings) } @PluginMethod @@ -91,6 +94,22 @@ class CameraPlugin : Plugin() { ionFlow.playVideo(call) } + @PluginMethod + fun chooseFromGallery(call: PluginCall) { + gallerySettings = getGallerySettings(call) + ionFlow.chooseFromGallery(call, gallerySettings) + } + + @PluginMethod + fun editPhoto(call: PluginCall) { + ionFlow.editPhoto(call) + } + + @PluginMethod + fun editURIPhoto(call: PluginCall) { + ionFlow.editURIPhoto(call) + } + @PluginMethod fun pickImages(call: PluginCall) { legacyFlow.pickImages(call) @@ -231,11 +250,22 @@ class CameraPlugin : Plugin() { return settings } - fun getVideoSettings(call: PluginCall): VideoSettings { - val settings = VideoSettings() - settings.saveToGallery = call.getBoolean("saveToGallery") ?: false - settings.includeMetadata = call.getBoolean("includeMetadata") ?: false - return settings + fun getVideoSettings(call: PluginCall): VideoSettings { + return VideoSettings( + saveToGallery = call.getBoolean("saveToGallery") ?: false, + includeMetadata = call.getBoolean("includeMetadata") ?: false + ) + } + + fun getGallerySettings(call: PluginCall): GallerySettings { + return GallerySettings( + mediaType = IONCAMRMediaType.fromValue((call.getInt("mediaType") ?: 0)), + allowMultipleSelection = call.getBoolean("allowMultipleSelection") ?: false, + includeMetadata = call.getBoolean("includeMetadata") ?: false, + allowEdit = call.getBoolean("allowEdit") ?: false, + limit = call.getInt("limit") ?: 0, + editInApp = call.getBoolean("editInApp") ?: true + ) } private fun getResultType(resultType: String?): CameraResultType? { diff --git a/android/src/main/java/com/capacitorjs/plugins/camera/GallerySettings.kt b/android/src/main/java/com/capacitorjs/plugins/camera/GallerySettings.kt new file mode 100644 index 0000000..4f0fe11 --- /dev/null +++ b/android/src/main/java/com/capacitorjs/plugins/camera/GallerySettings.kt @@ -0,0 +1,12 @@ +package com.capacitorjs.plugins.camera + +import io.ionic.libs.ioncameralib.model.IONCAMRMediaType + +data class GallerySettings( + val mediaType: IONCAMRMediaType = IONCAMRMediaType.ALL, + val allowMultipleSelection: Boolean = false, + val limit: Int = 0, + val includeMetadata: Boolean = false, + val allowEdit: Boolean = false, + val editInApp: Boolean = true +) \ No newline at end of file diff --git a/android/src/main/java/com/capacitorjs/plugins/camera/IonCameraFlow.kt b/android/src/main/java/com/capacitorjs/plugins/camera/IonCameraFlow.kt index 78675ed..19b6c37 100644 --- a/android/src/main/java/com/capacitorjs/plugins/camera/IonCameraFlow.kt +++ b/android/src/main/java/com/capacitorjs/plugins/camera/IonCameraFlow.kt @@ -8,29 +8,32 @@ import android.content.pm.PackageManager import android.graphics.BitmapFactory import android.net.Uri import android.os.Build -import android.util.Log import androidx.activity.result.ActivityResult import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.contract.ActivityResultContracts import androidx.core.content.FileProvider import com.getcapacitor.FileUtils import com.getcapacitor.JSObject -import com.getcapacitor.Logger import com.getcapacitor.PermissionState import com.getcapacitor.PluginCall -import io.ionic.libs.ioncameralib.helper.OSCAMRExifHelper -import io.ionic.libs.ioncameralib.helper.OSCAMRFileHelper -import io.ionic.libs.ioncameralib.helper.OSCAMRImageHelper -import io.ionic.libs.ioncameralib.helper.OSCAMRMediaHelper -import io.ionic.libs.ioncameralib.manager.CameraManager -import io.ionic.libs.ioncameralib.manager.VideoManager -import io.ionic.libs.ioncameralib.model.IONCameraParameters -import io.ionic.libs.ioncameralib.model.IONError -import io.ionic.libs.ioncameralib.model.IONMediaResult +import io.ionic.libs.ioncameralib.helper.IONCAMRExifHelper +import io.ionic.libs.ioncameralib.helper.IONCAMRFileHelper +import io.ionic.libs.ioncameralib.helper.IONCAMRImageHelper +import io.ionic.libs.ioncameralib.helper.IONCAMRMediaHelper +import io.ionic.libs.ioncameralib.manager.IONCAMRCameraManager +import io.ionic.libs.ioncameralib.manager.IONCAMRGalleryManager +import io.ionic.libs.ioncameralib.manager.IONCAMREditManager +import io.ionic.libs.ioncameralib.manager.IONCAMRVideoManager +import io.ionic.libs.ioncameralib.model.IONCAMRCameraParameters +import io.ionic.libs.ioncameralib.model.IONCAMREditParameters +import io.ionic.libs.ioncameralib.model.IONCAMRError +import io.ionic.libs.ioncameralib.model.IONCAMRMediaResult +import io.ionic.libs.ioncameralib.model.IONCAMRMediaType import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import org.json.JSONArray +import com.getcapacitor.JSArray import java.io.File @@ -38,44 +41,69 @@ class IonCameraFlow( private val plugin: CameraPlugin ) { private var isFirstRequest = true - private var cameraManager: CameraManager? = null - private var videoManager: VideoManager? = null + private var cameraManager: IONCAMRCameraManager? = null + private var videoManager: IONCAMRVideoManager? = null + private var editManager: IONCAMREditManager? = null + private var galleryManager: IONCAMRGalleryManager? = null private lateinit var cameraLauncher: ActivityResultLauncher - private lateinit var cropLauncher: ActivityResultLauncher - + private lateinit var cameraCropLauncher: ActivityResultLauncher + private lateinit var galleryCropLauncher: ActivityResultLauncher + private lateinit var galleryLauncher: ActivityResultLauncher private lateinit var videoLauncher: ActivityResultLauncher + private lateinit var editLauncher: ActivityResultLauncher private var currentCall: PluginCall? = null - private var settings = CameraSettings() - private var videoSettings = VideoSettings() + private var cameraSettings : CameraSettings? = null + private var videoSettings : VideoSettings? = null + private var gallerySettings : GallerySettings? = null + + private var editParameters = IONCAMREditParameters( + editURI = "", fromUri = false, saveToGallery = false, includeMetadata = false + ) fun load() { setupLaunchers() - cameraManager = CameraManager( + cameraManager = IONCAMRCameraManager( plugin.getAppId(), ".fileprovider", - OSCAMRExifHelper(), - OSCAMRFileHelper(), - OSCAMRMediaHelper(), - OSCAMRImageHelper() + IONCAMRExifHelper(), + IONCAMRFileHelper(), + IONCAMRMediaHelper(), + IONCAMRImageHelper() ) - videoManager = VideoManager( + videoManager = IONCAMRVideoManager( ".fileprovider", - OSCAMRFileHelper(), + IONCAMRFileHelper(), + ) + + galleryManager = IONCAMRGalleryManager( + IONCAMRExifHelper(), + IONCAMRFileHelper(), + IONCAMRMediaHelper(), + IONCAMRImageHelper() + ) + + editManager = IONCAMREditManager( + plugin.getAppId(), + ".fileprovider", + IONCAMRExifHelper(), + IONCAMRFileHelper(), + IONCAMRMediaHelper(), + IONCAMRImageHelper() ) cameraManager?.deleteVideoFilesFromCache(plugin.activity) } - fun takePhoto(call: PluginCall) { - settings = plugin.getSettings(call) + fun takePhoto(call: PluginCall, settings: CameraSettings) { + cameraSettings = settings currentCall = call - doShow(call) + showCamera(call) } - fun recordVideo(call: PluginCall) { - videoSettings = plugin.getVideoSettings(call) + fun recordVideo(call: PluginCall, settings: VideoSettings) { + videoSettings = settings currentCall = call openRecordVideo(call) } @@ -85,6 +113,22 @@ class IonCameraFlow( openPlayVideo(call) } + fun chooseFromGallery(call: PluginCall, settings: GallerySettings) { + gallerySettings = settings + currentCall = call + openGallery(call) + } + + fun editPhoto(call: PluginCall) { + currentCall = call + callEditPhoto(call) + } + + fun editURIPhoto(call: PluginCall) { + currentCall = call + callEditURIPhoto(call) + } + // ---------------------------------------------------- // Launchers // ---------------------------------------------------- @@ -95,10 +139,10 @@ class IonCameraFlow( handleCameraResult(result) } - cropLauncher = plugin.activity.registerForActivityResult( + cameraCropLauncher = plugin.activity.registerForActivityResult( ActivityResultContracts.StartActivityForResult() ) { result -> - handleCropResult(result) + handleCameraCropResult(result) } videoLauncher = plugin.activity.registerForActivityResult( @@ -107,93 +151,183 @@ class IonCameraFlow( handleVideoResult(result) } - } + galleryLauncher = plugin.activity.registerForActivityResult( + ActivityResultContracts.StartActivityForResult() + ) { result -> + handleGalleryResult(result) + } + + galleryCropLauncher = plugin.activity.registerForActivityResult( + ActivityResultContracts.StartActivityForResult() + ) { result -> + handleGalleryCropResult(result) + } - private fun doShow(call: PluginCall) { - when (settings.source) { - CameraSource.CAMERA -> showCamera(call) - // CameraSource.PHOTOS -> showPhotos(call) - else -> Log.d("CAMERA_DEBUG", "PROMPT ")//showPrompt(call) + editLauncher = plugin.activity.registerForActivityResult( + ActivityResultContracts.StartActivityForResult() + ) { result -> + handleEditResult(result) } + } private fun showCamera(call: PluginCall) { if (!plugin.getContext().getPackageManager() .hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY) ) { - sendError(IONError.NO_CAMERA_AVAILABLE_ERROR) + sendError(IONCAMRError.NO_CAMERA_AVAILABLE_ERROR) return } openCamera(call) } fun openCamera(call: PluginCall) { + + val settings = cameraSettings ?: run { + sendError(IONCAMRError.INVALID_ARGUMENT_ERROR) + return + } if (checkCameraPermissions(call, settings.saveToGallery)) { try { val manager = cameraManager ?: run { - sendError(IONError.CONTEXT_ERROR) + sendError(IONCAMRError.CONTEXT_ERROR) return } currentCall = call manager.takePhoto(plugin.getActivity(), CameraPlugin.ENCODING_TYPE, cameraLauncher) } catch (ex: Exception) { - sendError(IONError.FAILED_TO_CAPTURE_IMAGE_ERROR) + sendError(IONCAMRError.FAILED_TO_CAPTURE_IMAGE_ERROR) } } } fun openRecordVideo(call: PluginCall) { - if (checkCameraPermissions(call, videoSettings.saveToGallery)) { + val settings = videoSettings ?: run { + sendError(IONCAMRError.INVALID_ARGUMENT_ERROR) + return + } + + if (checkCameraPermissions(call, settings.saveToGallery)) { try { val manager = cameraManager ?: run { - sendError(IONError.CONTEXT_ERROR) + sendError(IONCAMRError.CONTEXT_ERROR) return } currentCall = call manager.recordVideo( plugin.getActivity(), - videoSettings.saveToGallery, + settings.saveToGallery, videoLauncher ) { sendError(it) } } catch (ex: Exception) { - sendError(IONError.VIDEO_CAPTURE_NOT_SUPPORTED_ERROR) + sendError(IONCAMRError.VIDEO_CAPTURE_NOT_SUPPORTED_ERROR) } } } private fun openPlayVideo(call: PluginCall) { try { + val manager = videoManager ?: run { + sendError(IONCAMRError.CONTEXT_ERROR) + return + } + val videoUri = call.getString("videoURI") - ?: return sendError(IONError.PLAY_VIDEO_GENERAL_ERROR) - videoManager?.playVideo(plugin.activity, videoUri, { + ?: return sendError(IONCAMRError.PLAY_VIDEO_GENERAL_ERROR) + manager.playVideo(plugin.activity, videoUri, { call.resolve() }, { sendError(it) }) } catch (_: Exception) { - sendError(IONError.PLAY_VIDEO_GENERAL_ERROR) + sendError(IONCAMRError.PLAY_VIDEO_GENERAL_ERROR) + return + } + } + + private fun openGallery(call: PluginCall) { + val manager = galleryManager ?: run { + sendError(IONCAMRError.CONTEXT_ERROR) + return + } + + val settings = gallerySettings ?: run { + sendError(IONCAMRError.INVALID_ARGUMENT_ERROR) + return + } + + manager.chooseFromGallery( + plugin.activity, + settings.mediaType, + settings.allowMultipleSelection, + settings.limit, + galleryLauncher + ) + } + + private fun callEditPhoto(call: PluginCall) { + val manager = editManager ?: run { + sendError(IONCAMRError.CONTEXT_ERROR) + return + } + + editParameters = IONCAMREditParameters( + "", + fromUri = false, + saveToGallery = false, + includeMetadata = false + ) + val imageBase64 = call.data.getString("base64") + if (imageBase64 == null) return + manager.editImage(plugin.activity, imageBase64, editLauncher) + } + + private fun callEditURIPhoto(call: PluginCall) { + val manager = editManager ?: run { + sendError(IONCAMRError.CONTEXT_ERROR) return } + + val photoPath = call.getString("uri") + val saveToGallery = call.getBoolean("saveToGallery") ?: false + val includeMetadata = call.getBoolean("includeMetadata") ?: false + if (photoPath == null) return + + editParameters = IONCAMREditParameters( + editURI = photoPath, + fromUri = true, + saveToGallery = saveToGallery, + includeMetadata = includeMetadata + ) + + manager.editURIPicture(plugin.activity, photoPath, editLauncher) { + sendError(IONCAMRError.EDIT_IMAGE_ERROR) + } } + private fun handleCameraResult(result: ActivityResult) { when (result.resultCode) { Activity.RESULT_OK -> { + val settings = cameraSettings ?: run { + sendError(IONCAMRError.INVALID_ARGUMENT_ERROR) + return + } if (settings.allowEditing) { editPhoto() } else { - processResult() + processResult(result) } } Activity.RESULT_CANCELED -> { - sendError(IONError.NO_PICTURE_TAKEN_ERROR) + sendError(IONCAMRError.NO_PICTURE_TAKEN_ERROR) } else -> { - sendError(IONError.TAKE_PHOTO_ERROR) + sendError(IONCAMRError.TAKE_PHOTO_ERROR) } } } @@ -205,16 +339,100 @@ class IonCameraFlow( } Activity.RESULT_CANCELED -> { - sendError(IONError.CAPTURE_VIDEO_CANCELLED_ERROR) + sendError(IONCAMRError.CAPTURE_VIDEO_CANCELLED_ERROR) } - else -> sendError(IONError.CAPTURE_VIDEO_ERROR) + else -> sendError(IONCAMRError.CAPTURE_VIDEO_ERROR) + } + } + + private fun handleGalleryResult(result: ActivityResult) { + when (result.resultCode) { + Activity.RESULT_OK -> { + + val editor = editManager ?: run { + sendError(IONCAMRError.CONTEXT_ERROR) + return + } + + val manager = galleryManager ?: run { + sendError(IONCAMRError.CONTEXT_ERROR) + return + } + + val settings = gallerySettings ?: run { + sendError(IONCAMRError.INVALID_ARGUMENT_ERROR) + return + } + + val uris = manager.extractUris(result.data) + + if (uris.isEmpty()) { + sendError(IONCAMRError.GENERIC_CHOOSE_MULTIMEDIA_ERROR) + return + } + + if (settings.allowEdit && uris.size == 1 && settings.mediaType == IONCAMRMediaType.PICTURE) { + editor.openCropActivity( + plugin.activity, + uris.first(), + galleryCropLauncher + ) + } else { + processResultFromGallery(result) + } + } + + Activity.RESULT_CANCELED -> { + sendError(IONCAMRError.CHOOSE_MULTIMEDIA_CANCELLED_ERROR) + } + + else -> sendError(IONCAMRError.GENERIC_CHOOSE_MULTIMEDIA_ERROR) + } + } + + private fun handleGalleryCropResult(result: ActivityResult) { + when (result.resultCode) { + Activity.RESULT_OK -> { + val manager = galleryManager ?: run { + sendError(IONCAMRError.CONTEXT_ERROR) + return + } + + val settings = gallerySettings ?: run { + sendError(IONCAMRError.INVALID_ARGUMENT_ERROR) + return + } + + CoroutineScope(Dispatchers.Default).launch { + manager.onChooseFromGalleryEditResult( + plugin.activity, + result.resultCode, + result.data, + settings.includeMetadata, + { + handleGalleryMediaResults(it) + }, + { sendError(it) }) + } + } + + Activity.RESULT_CANCELED -> sendError(IONCAMRError.EDIT_OPERATION_CANCELLED_ERROR) + else -> sendError(IONCAMRError.EDIT_IMAGE_ERROR) + } + } + + private fun handleEditResult(result: ActivityResult) { + when (result.resultCode) { + Activity.RESULT_OK -> processResultFromEdit(result) + Activity.RESULT_CANCELED -> sendError(IONCAMRError.EDIT_OPERATION_CANCELLED_ERROR) + else -> sendError(IONCAMRError.EDIT_IMAGE_ERROR) } } private fun editPhoto() { - val manager = cameraManager ?: run { - sendError(IONError.CONTEXT_ERROR) + val editor = editManager ?: run { + sendError(IONCAMRError.CONTEXT_ERROR) return } @@ -222,7 +440,7 @@ class IonCameraFlow( val tmpFile = FileProvider.getUriForFile( plugin.activity, "$appId.fileprovider", - manager.createCaptureFile( + editor.createCaptureFile( plugin.activity, CameraPlugin.ENCODING_TYPE, plugin.activity.getSharedPreferences( @@ -232,25 +450,30 @@ class IonCameraFlow( ) ) - manager.openCropActivity( + editor.openCropActivity( plugin.activity, tmpFile, - cropLauncher + cameraCropLauncher ) } - private fun handleCropResult(result: ActivityResult) { + private fun handleCameraCropResult(result: ActivityResult) { when (result.resultCode) { - Activity.RESULT_OK -> processResult() - Activity.RESULT_CANCELED -> sendError(IONError.EDIT_OPERATION_CANCELLED_ERROR) - else -> sendError(IONError.EDIT_IMAGE_ERROR) + Activity.RESULT_OK -> processResult(result) + Activity.RESULT_CANCELED -> sendError(IONCAMRError.EDIT_OPERATION_CANCELLED_ERROR) + else -> sendError(IONCAMRError.EDIT_IMAGE_ERROR) } } - private fun handleBase64Result(image: String) { + private fun handlePhotoBase64Result(image: String) { val ret = JSObject() ret.put("format", "jpeg") + val settings = cameraSettings ?: run { + sendError(IONCAMRError.INVALID_ARGUMENT_ERROR) + return + } + when (settings.resultType) { CameraResultType.BASE64 -> { ret.put("base64String", image) @@ -261,20 +484,30 @@ class IonCameraFlow( } else -> { - sendError(IONError.PROCESS_IMAGE_ERROR) + sendError(IONCAMRError.PROCESS_IMAGE_ERROR) return } } + + currentCall?.resolve(ret) + currentCall = null + } + + private fun handleEditBase64Result(image: String) { + val ret = JSObject() + ret.put("format", "jpeg") + ret.put("base64String", image) currentCall?.resolve(ret) currentCall = null } - private fun handleMediaResult(mediaResult: IONMediaResult) { + + private fun handleMediaResult(mediaResult: IONCAMRMediaResult) { val file = File(mediaResult.uri) val uri = Uri.fromFile(file) val bitmap = BitmapFactory.decodeFile(mediaResult.uri) if (bitmap == null) { - sendError(IONError.PROCESS_IMAGE_ERROR) + sendError(IONCAMRError.PROCESS_IMAGE_ERROR) return } @@ -282,15 +515,14 @@ class IonCameraFlow( val ret = JSObject() ret.put("format", "jpeg") ret.put("exif", exif.toJson()) - ret.put("path", uri.toString()) + ret.put("path", mediaResult.uri) ret.put("webPath", FileUtils.getPortablePath(plugin.context, plugin.bridge.localUrl, uri)) ret.put("saved", mediaResult.saved) currentCall?.resolve(ret) currentCall = null - } - private fun handleVideoMediaResult(mediaResult: IONMediaResult) { + private fun handleVideoMediaResult(mediaResult: IONCAMRMediaResult) { val file = File(mediaResult.uri) val uri = Uri.fromFile(file) @@ -308,14 +540,52 @@ class IonCameraFlow( currentCall = null } - private fun processResult() { - val manager = cameraManager ?: return + private fun handleGalleryMediaResults(results: List) { + val photos = JSArray() + results.forEach { mediaResult -> + val file = File(mediaResult.uri) + val uri = Uri.fromFile(file) + + val obj = JSObject() + obj.put("path", mediaResult.uri) + obj.put( + "webPath", + FileUtils.getPortablePath(plugin.context, plugin.bridge.localUrl, uri) + ) + obj.put("saved", mediaResult.saved) + + mediaResult.metadata?.let { + obj.put("duration", it.duration) + obj.put("size", it.size) + obj.put("format", it.format) + } + + photos.put(obj) + } + + val ret = JSObject() + ret.put("photos", photos) + currentCall?.resolve(ret) + currentCall = null + } + + private fun processResult(result: ActivityResult) { + val manager = cameraManager ?: run { + sendError(IONCAMRError.CONTEXT_ERROR) + return + } + + val settings = cameraSettings ?: run { + sendError(IONCAMRError.INVALID_ARGUMENT_ERROR) + return + } val ionParams = settings.toIonParameters() manager.processResultFromCamera( plugin.activity, + result.data, ionParams, { image -> - handleBase64Result(image) + handlePhotoBase64Result(image) }, { mediaResult -> handleMediaResult(mediaResult) @@ -327,6 +597,10 @@ class IonCameraFlow( } private fun processResultFromVideo(result: ActivityResult) { + val manager = cameraManager ?: run { + sendError(IONCAMRError.CONTEXT_ERROR) + return + } var uri = result.data?.data if (uri == null) { val fromPreferences = @@ -335,28 +609,78 @@ class IonCameraFlow( fromPreferences.let { uri = Uri.parse(fromPreferences) } } if (plugin.activity == null) { - sendError(IONError.CAPTURE_VIDEO_ERROR) + sendError(IONCAMRError.CAPTURE_VIDEO_ERROR) + return + } + val settings = videoSettings ?: run { + sendError(IONCAMRError.INVALID_ARGUMENT_ERROR) return } CoroutineScope(Dispatchers.Default).launch { - cameraManager?.processResultFromVideo( + manager.processResultFromVideo( plugin.activity, uri, - videoSettings.saveToGallery, - videoSettings.includeMetadata, + settings.saveToGallery, + settings.includeMetadata, { mediaResult -> handleVideoMediaResult(mediaResult) }, { - sendError(IONError.CAPTURE_VIDEO_ERROR) + sendError(IONCAMRError.CAPTURE_VIDEO_ERROR) }) } } - private fun CameraSettings.toIonParameters(): IONCameraParameters { + private fun processResultFromGallery(result: ActivityResult) { + val manager = galleryManager ?: run { + sendError(IONCAMRError.CONTEXT_ERROR) + return + } + + val settings = gallerySettings ?: run { + sendError(IONCAMRError.INVALID_ARGUMENT_ERROR) + return + } + + CoroutineScope(Dispatchers.Default).launch { + manager.onChooseFromGalleryResult( + plugin.activity, + result.resultCode, + result.data, + settings.includeMetadata, + { + handleGalleryMediaResults(it) + }, + { sendError(it) }) + } + } + + private fun processResultFromEdit(result: ActivityResult) { + val manager = editManager ?: run { + sendError(IONCAMRError.CONTEXT_ERROR) + return + } + + manager.processResultFromEdit( + plugin.activity, + result.data, + editParameters, + { image -> + handleEditBase64Result(image) + }, + { mediaResult -> + handleMediaResult(mediaResult) + }, + { error -> + sendError(error) + } + ) + } + + private fun CameraSettings.toIonParameters(): IONCAMRCameraParameters { val useLatestVersion = (resultType == CameraResultType.URI) - return IONCameraParameters( + return IONCAMRCameraParameters( mQuality = quality, targetWidth = width, targetHeight = height, @@ -365,7 +689,8 @@ class IonCameraFlow( allowEdit = allowEditing, correctOrientation = shouldCorrectOrientation, saveToPhotoAlbum = saveToGallery, - includeMetadata = true, // Keep true + //TODO this value should come from settings, possibly from new interface TakePhotoOptions + includeMetadata = false, latestVersion = useLatestVersion ) } @@ -416,21 +741,19 @@ class IonCameraFlow( fun handleCameraPermissionsCallback(call: PluginCall) { if (plugin.getPermissionState(CameraPlugin.CAMERA) != PermissionState.GRANTED) { - sendError(IONError.CAMERA_PERMISSION_DENIED_ERROR) + sendError(IONCAMRError.CAMERA_PERMISSION_DENIED_ERROR) return } when (call.getMethodName()) { "takePhoto" -> openCamera(call) "recordVideo" -> openRecordVideo(call) - "pickImages" -> { - // openPhotos(call) - } - else -> sendError(IONError.CONTEXT_ERROR) + "pickImages" -> openGallery(call) + else -> sendError(IONCAMRError.CONTEXT_ERROR) } } - private fun sendError(error: IONError) { + private fun sendError(error: IONCAMRError) { try { val jsonResult = JSObject() jsonResult.put("code", formatErrorCode(error.code)) diff --git a/android/src/main/java/com/capacitorjs/plugins/camera/LegacyCameraFlow.java b/android/src/main/java/com/capacitorjs/plugins/camera/LegacyCameraFlow.java index 8c94038..e9ed8ef 100644 --- a/android/src/main/java/com/capacitorjs/plugins/camera/LegacyCameraFlow.java +++ b/android/src/main/java/com/capacitorjs/plugins/camera/LegacyCameraFlow.java @@ -1,6 +1,5 @@ package com.capacitorjs.plugins.camera; - import android.app.Activity; import android.content.ActivityNotFoundException; import android.content.ContentResolver; @@ -123,17 +122,17 @@ private void showPrompt(final PluginCall call) { final CameraBottomSheetDialogFragment fragment = new CameraBottomSheetDialogFragment(); fragment.setTitle(call.getString("promptLabelHeader", "Photo")); fragment.setOptions( - options, - (index) -> { - if (index == 0) { - settings.setSource(CameraSource.PHOTOS); - openPhotos(call); - } else if (index == 1) { - settings.setSource(CameraSource.CAMERA); - openCamera(call); - } - }, - () -> call.reject(USER_CANCELLED) + options, + (index) -> { + if (index == 0) { + settings.setSource(CameraSource.PHOTOS); + openPhotos(call); + } else if (index == 1) { + settings.setSource(CameraSource.CAMERA); + openCamera(call); + } + }, + () -> call.reject(USER_CANCELLED) ); fragment.show(plugin.getActivity().getSupportFragmentManager(), "capacitorModalsActionSheet"); } @@ -229,8 +228,8 @@ public void openPhotos(final PluginCall call) { } private ActivityResultLauncher registerActivityResultLauncher( - ActivityResultContract contract, - ActivityResultCallback callback + ActivityResultContract contract, + ActivityResultCallback callback ) { String key = "cap_activity_rq#" + mNextLocalRequestCode.getAndIncrement(); if (plugin.getBridge().getFragment() != null) { @@ -245,6 +244,14 @@ private ActivityResultLauncher registerActivityResultLauncher( private ActivityResultContract> getContractForCall(final PluginCall call) { int limit = call.getInt("limit", 0); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + int maxLimit = MediaStore.getPickImagesMaxLimit(); + if (limit > maxLimit) { + limit = maxLimit; + } + } + if (limit > 1) { return new ActivityResultContracts.PickMultipleVisualMedia(limit); } else { @@ -283,7 +290,7 @@ private void openPhotos(final PluginCall call, boolean multiple) { pickMultipleMedia.unregister(); }); pickMultipleMedia.launch( - new PickVisualMediaRequest.Builder().setMediaType(ActivityResultContracts.PickVisualMedia.ImageOnly.INSTANCE).build() + new PickVisualMediaRequest.Builder().setMediaType(ActivityResultContracts.PickVisualMedia.ImageOnly.INSTANCE).build() ); } else { pickMedia = registerActivityResultLauncher(new ActivityResultContracts.PickVisualMedia(), (uri) -> { @@ -296,7 +303,7 @@ private void openPhotos(final PluginCall call, boolean multiple) { pickMedia.unregister(); }); pickMedia.launch( - new PickVisualMediaRequest.Builder().setMediaType(ActivityResultContracts.PickVisualMedia.ImageOnly.INSTANCE).build() + new PickVisualMediaRequest.Builder().setMediaType(ActivityResultContracts.PickVisualMedia.ImageOnly.INSTANCE).build() ); } } catch (ActivityNotFoundException ex) { @@ -540,10 +547,10 @@ private void returnResult(PluginCall call, Bitmap bitmap, Uri u) { } } else { String inserted = MediaStore.Images.Media.insertImage( - plugin.getContext().getContentResolver(), - fileToSavePath, - fileToSave.getName(), - "" + plugin.getContext().getContentResolver(), + fileToSavePath, + fileToSave.getName(), + "" ); if (inserted == null) { @@ -691,7 +698,11 @@ private void editImage(PluginCall call, Uri uri, ByteArrayOutputStream bitmapOut private Intent createEditIntent(Uri origPhotoUri) { try { File editFile = new File(origPhotoUri.getPath()); - Uri editUri = FileProvider.getUriForFile(plugin.getActivity(), plugin.getContext().getPackageName() + ".fileprovider", editFile); + Uri editUri = FileProvider.getUriForFile( + plugin.getActivity(), + plugin.getContext().getPackageName() + ".fileprovider", + editFile + ); Intent editIntent = new Intent(Intent.ACTION_EDIT); editIntent.setDataAndType(editUri, "image/*"); imageEditedFileSavePath = editFile.getAbsolutePath(); @@ -702,9 +713,10 @@ private Intent createEditIntent(Uri origPhotoUri) { List resInfoList; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - resInfoList = plugin.getContext() - .getPackageManager() - .queryIntentActivities(editIntent, PackageManager.ResolveInfoFlags.of(PackageManager.MATCH_DEFAULT_ONLY)); + resInfoList = plugin + .getContext() + .getPackageManager() + .queryIntentActivities(editIntent, PackageManager.ResolveInfoFlags.of(PackageManager.MATCH_DEFAULT_ONLY)); } else { resInfoList = legacyQueryIntentActivities(editIntent); } @@ -745,5 +757,4 @@ public void onDestroy() { pickMultipleMedia.unregister(); } } - -} \ No newline at end of file +} diff --git a/android/src/main/java/com/capacitorjs/plugins/camera/VideoSettings.kt b/android/src/main/java/com/capacitorjs/plugins/camera/VideoSettings.kt index 2a6d034..aaf1ad7 100644 --- a/android/src/main/java/com/capacitorjs/plugins/camera/VideoSettings.kt +++ b/android/src/main/java/com/capacitorjs/plugins/camera/VideoSettings.kt @@ -1,6 +1,6 @@ package com.capacitorjs.plugins.camera -class VideoSettings { - var saveToGallery: Boolean = false - var includeMetadata: Boolean = false -} \ No newline at end of file +data class VideoSettings( + val saveToGallery: Boolean = false, + val includeMetadata: Boolean = false +) \ No newline at end of file diff --git a/example-app/android/app/capacitor.build.gradle b/example-app/android/app/capacitor.build.gradle index a76c716..c7720d1 100644 --- a/example-app/android/app/capacitor.build.gradle +++ b/example-app/android/app/capacitor.build.gradle @@ -10,6 +10,8 @@ android { apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle" dependencies { implementation project(':capacitor-camera') + implementation project(':capacitor-filesystem') + implementation project(':capacitor-file-viewer') } diff --git a/example-app/android/capacitor.settings.gradle b/example-app/android/capacitor.settings.gradle index d05dba8..df71738 100644 --- a/example-app/android/capacitor.settings.gradle +++ b/example-app/android/capacitor.settings.gradle @@ -4,3 +4,9 @@ project(':capacitor-android').projectDir = new File('../node_modules/@capacitor/ include ':capacitor-camera' project(':capacitor-camera').projectDir = new File('../../android') + +include ':capacitor-filesystem' +project(':capacitor-filesystem').projectDir = new File('../node_modules/@capacitor/filesystem/android') + +include ':capacitor-file-viewer' +project(':capacitor-file-viewer').projectDir = new File('../node_modules/@capacitor/file-viewer/android') diff --git a/example-app/ios/App/CapApp-SPM/Package.swift b/example-app/ios/App/CapApp-SPM/Package.swift index b61c35e..6b8f98e 100644 --- a/example-app/ios/App/CapApp-SPM/Package.swift +++ b/example-app/ios/App/CapApp-SPM/Package.swift @@ -12,7 +12,9 @@ let package = Package( ], dependencies: [ .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", exact: "8.2.0"), - .package(name: "CapacitorCamera", path: "../../../..") + .package(name: "CapacitorCamera", path: "../../../.."), + .package(name: "CapacitorFilesystem", path: "../../../node_modules/@capacitor/filesystem"), + .package(name: "CapacitorFileViewer", path: "../../../node_modules/@capacitor/file-viewer") ], targets: [ .target( @@ -20,7 +22,9 @@ let package = Package( dependencies: [ .product(name: "Capacitor", package: "capacitor-swift-pm"), .product(name: "Cordova", package: "capacitor-swift-pm"), - .product(name: "CapacitorCamera", package: "CapacitorCamera") + .product(name: "CapacitorCamera", package: "CapacitorCamera"), + .product(name: "CapacitorFilesystem", package: "CapacitorFilesystem"), + .product(name: "CapacitorFileViewer", package: "CapacitorFileViewer") ] ) ] diff --git a/example-app/package-lock.json b/example-app/package-lock.json index f37f0ed..75f8284 100644 --- a/example-app/package-lock.json +++ b/example-app/package-lock.json @@ -11,16 +11,20 @@ "@capacitor/android": "^8.0.0", "@capacitor/camera": "file:../", "@capacitor/core": "^8.0.0", + "@capacitor/file-viewer": "^2.0.1", + "@capacitor/filesystem": "^8.1.2", "@capacitor/ios": "^8.0.0", - "@ionic/react": "^8.5.0", - "@ionic/react-router": "^8.5.0", + "@ionic/pwa-elements": "^3.4.0", + "@ionic/react": "^8.8.1", + "@ionic/react-router": "^8.8.1", "@types/react-router": "^5.1.20", "@types/react-router-dom": "^5.3.3", "ionicons": "^7.4.0", "react": "19.0.0", "react-dom": "19.0.0", "react-router": "^5.3.4", - "react-router-dom": "^5.3.4" + "react-router-dom": "^5.3.4", + "swiper": "^12.1.2" }, "devDependencies": { "@capacitor/cli": "^8.0.0", @@ -109,6 +113,7 @@ "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -1722,10 +1727,35 @@ "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-8.2.0.tgz", "integrity": "sha512-oKaoNeNtH2iIZMDFVrb1atoyRECDGHcfLMunJ5KWN8DtvpVBeeA4c41e20NTuhMxw1cSYbpq2PV2hb+/9CJxlQ==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.1.0" } }, + "node_modules/@capacitor/file-viewer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@capacitor/file-viewer/-/file-viewer-2.0.1.tgz", + "integrity": "sha512-1kICpFCCFi/Tr47jVmN1TWbViJhMA/kvXogC16Em87brmng0rgaGiFfiFi9bMNuDCMs17xG7ov7Rj0sUxrZBSA==", + "license": "MIT", + "dependencies": { + "@capacitor/synapse": "^1.0.4" + }, + "peerDependencies": { + "@capacitor/core": ">=8.0.0" + } + }, + "node_modules/@capacitor/filesystem": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/@capacitor/filesystem/-/filesystem-8.1.2.tgz", + "integrity": "sha512-doaaMfGoFR2hWU6aV6u83I+5ZsGyJVq+Gz4r9lMpJzUKMm1eMu0hLnFdV1aXZlU9FlK/RndFrVD8oRZfNOqWgQ==", + "license": "MIT", + "dependencies": { + "@capacitor/synapse": "^1.0.4" + }, + "peerDependencies": { + "@capacitor/core": ">=8.0.0" + } + }, "node_modules/@capacitor/ios": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/@capacitor/ios/-/ios-8.2.0.tgz", @@ -1735,6 +1765,12 @@ "@capacitor/core": "^8.2.0" } }, + "node_modules/@capacitor/synapse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@capacitor/synapse/-/synapse-1.0.4.tgz", + "integrity": "sha512-/C1FUo8/OkKuAT4nCIu/34ny9siNHr9qtFezu4kxm6GY1wNFxrCFWjfYx5C1tUhVGz3fxBABegupkpjXvjCHrw==", + "license": "ISC" + }, "node_modules/@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", @@ -2435,6 +2471,16 @@ "@stencil/core": "^4.35.3" } }, + "node_modules/@ionic/pwa-elements": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@ionic/pwa-elements/-/pwa-elements-3.4.0.tgz", + "integrity": "sha512-WmL7An4NOsvJvct4V/A8hudr+yXgLBHYmxzqWGsetZmzN7C6suLRS/KIh2P1t8cSYCYL7HRrbv8NrIChPkh6Ow==", + "license": "MIT", + "engines": { + "node": ">=16.0.0", + "npm": ">=8.0.0" + } + }, "node_modules/@ionic/react": { "version": "8.8.1", "resolved": "https://registry.npmjs.org/@ionic/react/-/react-8.8.1.tgz", @@ -3165,6 +3211,7 @@ "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", @@ -3311,7 +3358,8 @@ "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.20.tgz", "integrity": "sha512-/pC9HAB5I/xMlc5FP77qjCnI16ChlJfW0tGa0IUcFn38VJrTV6DeZ60NU5KZBtaOZqjdpwTWohz5HU1RrhiYxQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@types/chai-subset": { "version": "1.3.6", @@ -3441,6 +3489,7 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.0.10.tgz", "integrity": "sha512-JuRQ9KXLEjaUNjTWpzuR231Z2WpIwczOkBEIvbHNCzQefFIT0L8IqE6NV6ULLyC1SI/i234JnDoMkfg+RjQj2g==", "license": "MIT", + "peer": true, "dependencies": { "csstype": "^3.0.2" } @@ -3451,6 +3500,7 @@ "integrity": "sha512-4fSQ8vWFkg+TGhePfUzVmat3eC14TXYSsiiDSLI0dVLsrm9gZFABjPy/Qu6TKgl1tq1Bu1yDsuQgY3A3DOjCcg==", "dev": true, "license": "MIT", + "peer": true, "peerDependencies": { "@types/react": "^19.0.0" } @@ -3587,6 +3637,7 @@ "integrity": "sha512-XZzOmihLIr8AD1b9hL9ccNMzEMWt/dE2u7NyTY9jJG6YNiNthaD5XtUHVF2uCXZ15ng+z2hT3MVuxnUYhq6k1g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.57.0", "@typescript-eslint/types": "8.57.0", @@ -4121,6 +4172,7 @@ "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -4691,6 +4743,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -5598,6 +5651,7 @@ "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" @@ -5874,6 +5928,7 @@ "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -9191,6 +9246,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.0.0.tgz", "integrity": "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -9200,6 +9256,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0.tgz", "integrity": "sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==", "license": "MIT", + "peer": true, "dependencies": { "scheduler": "^0.25.0" }, @@ -9229,6 +9286,7 @@ "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz", "integrity": "sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==", "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.12.13", "history": "^4.9.0", @@ -9249,6 +9307,7 @@ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.4.tgz", "integrity": "sha512-m4EqFMHv/Ih4kpcBCONHbkT68KoAeHN4p3lAGoNryfHi0dMy0kCzEZakiKRsvg5wHZ/JLrLW8o8KomWiz/qbYQ==", "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.12.13", "history": "^4.9.0", @@ -10331,6 +10390,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/swiper": { + "version": "12.1.2", + "resolved": "https://registry.npmjs.org/swiper/-/swiper-12.1.2.tgz", + "integrity": "sha512-4gILrI3vXZqoZh71I1PALqukCFgk+gpOwe1tOvz5uE9kHtl2gTDzmYflYCwWvR4LOvCrJi6UEEU+gnuW5BtkgQ==", + "funding": [ + { + "type": "patreon", + "url": "https://www.patreon.com/swiperjs" + }, + { + "type": "open_collective", + "url": "http://opencollective.com/swiper" + } + ], + "license": "MIT", + "engines": { + "node": ">= 4.7.0" + } + }, "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", @@ -10378,6 +10456,7 @@ "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", @@ -10706,6 +10785,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -10931,6 +11011,7 @@ "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", diff --git a/example-app/package.json b/example-app/package.json index c762339..b2d3e40 100644 --- a/example-app/package.json +++ b/example-app/package.json @@ -15,16 +15,20 @@ "@capacitor/android": "^8.0.0", "@capacitor/camera": "file:../", "@capacitor/core": "^8.0.0", + "@capacitor/filesystem": "^8.1.2", + "@capacitor/file-viewer": "^2.0.1", "@capacitor/ios": "^8.0.0", - "@ionic/react": "^8.5.0", - "@ionic/react-router": "^8.5.0", + "@ionic/pwa-elements": "^3.4.0", + "@ionic/react": "^8.8.1", + "@ionic/react-router": "^8.8.1", "@types/react-router": "^5.1.20", "@types/react-router-dom": "^5.3.3", "ionicons": "^7.4.0", "react": "19.0.0", "react-dom": "19.0.0", "react-router": "^5.3.4", - "react-router-dom": "^5.3.4" + "react-router-dom": "^5.3.4", + "swiper": "^12.1.2" }, "devDependencies": { "@capacitor/cli": "^8.0.0", diff --git a/example-app/public/capacitorjs.png b/example-app/public/capacitorjs.png new file mode 100644 index 0000000..697927e Binary files /dev/null and b/example-app/public/capacitorjs.png differ diff --git a/example-app/public/flower.jpg b/example-app/public/flower.jpg new file mode 100644 index 0000000..b0f2052 Binary files /dev/null and b/example-app/public/flower.jpg differ diff --git a/example-app/src/App.tsx b/example-app/src/App.tsx index 8892f7b..a45eb7e 100644 --- a/example-app/src/App.tsx +++ b/example-app/src/App.tsx @@ -25,6 +25,11 @@ import '@ionic/react/css/text-transformation.css'; import '@ionic/react/css/flex-utils.css'; import '@ionic/react/css/display.css'; +import { defineCustomElements } from '@ionic/pwa-elements/loader'; + +// enable PWA elements +defineCustomElements(window); + /** * Ionic Dark Mode * ----------------------------------------------------- diff --git a/example-app/src/components/ExploreContainer.css b/example-app/src/components/ExploreContainer.css deleted file mode 100644 index c2c47cf..0000000 --- a/example-app/src/components/ExploreContainer.css +++ /dev/null @@ -1,24 +0,0 @@ -#container { - text-align: center; - position: absolute; - left: 0; - right: 0; - top: 50%; - transform: translateY(-50%); -} - -#container strong { - font-size: 20px; - line-height: 26px; -} - -#container p { - font-size: 16px; - line-height: 22px; - color: #8c8c8c; - margin: 0; -} - -#container a { - text-decoration: none; -} \ No newline at end of file diff --git a/example-app/src/components/ExploreContainer.tsx b/example-app/src/components/ExploreContainer.tsx deleted file mode 100644 index 1b68a3c..0000000 --- a/example-app/src/components/ExploreContainer.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import './ExploreContainer.css'; - -interface ContainerProps { } - -const ExploreContainer: React.FC = () => { - return ( -
- Ready to create an app? -

Start with Ionic UI Components

-
- ); -}; - -export default ExploreContainer; diff --git a/example-app/src/components/camera/ChooseFromGalleryConfigurable.tsx b/example-app/src/components/camera/ChooseFromGalleryConfigurable.tsx new file mode 100644 index 0000000..b0de67d --- /dev/null +++ b/example-app/src/components/camera/ChooseFromGalleryConfigurable.tsx @@ -0,0 +1,197 @@ +import { + IonButton, + IonAccordion, + IonAccordionGroup, + IonItem, + IonLabel, + IonSelect, + IonSelectOption, + IonToggle, +} from "@ionic/react"; +import React from "react"; +import { + Camera, + GalleryPhoto, + MediaType, +} from "@capacitor/camera"; + +interface ChooseFromGalleryConfig { + mediaType: number; + allowMultipleSelection: boolean; + includeMetadata: boolean; + allowEdit: boolean; +} + +interface ChooseFromGalleryConfigurableProps { + buttonLabel?: string; + onMediaResult: (media: GalleryPhoto[]) => void; +} + +interface ChooseFromGalleryConfigurableState { + config: ChooseFromGalleryConfig; +} + +class ChooseFromGalleryConfigurable extends React.Component< + ChooseFromGalleryConfigurableProps, + ChooseFromGalleryConfigurableState +> { + constructor(props: ChooseFromGalleryConfigurableProps) { + super(props); + this.state = { + config: { + mediaType: MediaType.picture, + allowMultipleSelection: false, + includeMetadata: false, + allowEdit: false, + }, + }; + } + + updateConfig = (field: keyof ChooseFromGalleryConfig, value: any): void => { + this.setState({ + config: { ...this.state.config, [field]: value }, + }); + }; + + executeDefault = async (): Promise => { + try { + const result = await Camera.chooseFromGallery({ + mediaType: MediaType.all, + allowMultipleSelection: true, + includeMetadata: false, + allowEdit: false, + limit: 2 + }); + console.log("chooseFromGallery result", result); + + // Convert MediaResult[] to GalleryPhoto[] + const galleryPhotos: GalleryPhoto[] = result.photos.map(photo => ({ + path: photo.path, + webPath: photo.webPath, + format: photo.format, + exif: undefined, // MediaResult doesn't include exif + })); + + this.props.onMediaResult(galleryPhotos); + } catch (e) { + const error = e as any; + const errorMessage = error.code ? `[${error.code}] ${error.message}` : error.message; + alert(`Failed to choose from gallery with error:\n${errorMessage}`); + } + }; + + executeWithConfig = async (): Promise => { + try { + const config = this.state.config; + const result = await Camera.chooseFromGallery({ + mediaType: config.mediaType, + allowMultipleSelection: config.allowMultipleSelection, + includeMetadata: config.includeMetadata, + allowEdit: config.allowEdit, + }); + console.log("chooseFromGallery result", result); + + // Convert MediaResult[] to GalleryPhoto[] + const galleryPhotos: GalleryPhoto[] = result.photos.map(photo => ({ + path: photo.path, + webPath: photo.webPath, + format: photo.format, + exif: undefined, // MediaResult doesn't include exif + })); + + this.props.onMediaResult(galleryPhotos); + } catch (e) { + const error = e as any; + const errorMessage = error.code ? `[${error.code}] ${error.message}` : error.message; + alert(`Failed to choose from gallery with error:\n${errorMessage}`); + } + }; + + render() { + const { buttonLabel = "chooseFromGallery (Default)" } = this.props; + const { config } = this.state; + + return ( + <> + this.executeDefault()} + style={{ marginTop: "16px" }} + > + {buttonLabel} + + + + + + + Expand to call chooseFromGallery with configurable options + + +
+ + Media Type + + this.updateConfig("mediaType", parseInt(e.detail.value!)) + } + > + Picture + Video + All + + + + + Allow Multiple Selection + + this.updateConfig("allowMultipleSelection", e.detail.checked) + } + /> + + + + Include Metadata + + this.updateConfig("includeMetadata", e.detail.checked) + } + /> + + + + Allow Edit + + this.updateConfig("allowEdit", e.detail.checked) + } + /> + + + this.executeWithConfig()} + > + Execute chooseFromGallery with Configuration + +
+
+
+ + ); + } +} + +export default ChooseFromGalleryConfigurable; diff --git a/example-app/src/components/camera/EditPhotoConfigurable.tsx b/example-app/src/components/camera/EditPhotoConfigurable.tsx new file mode 100644 index 0000000..1867e8e --- /dev/null +++ b/example-app/src/components/camera/EditPhotoConfigurable.tsx @@ -0,0 +1,196 @@ +import { + IonButton, + IonCard, + IonCardContent, + IonCardHeader, + IonCardTitle, +} from "@ionic/react"; +import React from "react"; +import { + Camera, + EditPhotoResult, +} from "@capacitor/camera"; +import { TestImage } from "./TestImageData"; + +interface EditPhotoConfigurableProps { + selectedImage: TestImage | null; +} + +interface EditPhotoConfigurableState { + base64Image: string | null; + editedResult: EditPhotoResult | null; + isLoading: boolean; +} + +class EditPhotoConfigurable extends React.Component< + EditPhotoConfigurableProps, + EditPhotoConfigurableState +> { + constructor(props: EditPhotoConfigurableProps) { + super(props); + this.state = { + base64Image: null, + editedResult: null, + isLoading: false, + }; + } + + componentDidUpdate(prevProps: EditPhotoConfigurableProps): void { + if (this.props.selectedImage !== prevProps.selectedImage) { + this.setState({ + base64Image: null, + editedResult: null, + }); + } + } + + loadImageAsBase64 = async (): Promise => { + if (!this.props.selectedImage) { + alert("No image selected. Please select an image first."); + return; + } + + this.setState({ isLoading: true }); + + try { + const image = this.props.selectedImage; + + if (image.type === "base64") { + this.setState({ + base64Image: image.data, + editedResult: null, + isLoading: false, + }); + } else { + // Asset image - fetch and convert to base64 + const response = await fetch(image.data); + const blob = await response.blob(); + const reader = new FileReader(); + + reader.onloadend = () => { + const base64String = reader.result as string; + // Remove the data:image/...;base64, prefix + const base64Data = base64String.split(",")[1]; + this.setState({ + base64Image: base64Data, + editedResult: null, + isLoading: false, + }); + }; + + reader.onerror = () => { + alert("Failed to convert image to base64"); + this.setState({ isLoading: false }); + }; + + reader.readAsDataURL(blob); + } + } catch (e) { + const error = e as any; + const errorMessage = error.code ? `[${error.code}] ${error.message}` : error.message; + alert(`Failed to load image with error:\n${errorMessage}`); + this.setState({ isLoading: false }); + } + }; + + editPhoto = async (): Promise => { + if (!this.state.base64Image) { + alert("No photo loaded. Please load an image first."); + return; + } + + try { + const result = await Camera.editPhoto({ + base64: this.state.base64Image, + }); + this.setState({ editedResult: result }); + } catch (e) { + const error = e as any; + const errorMessage = error.code ? `[${error.code}] ${error.message}` : error.message; + alert(`Failed to edit photo with error:\n${errorMessage}`); + } + }; + + clearPhotos = (): void => { + this.setState({ + base64Image: null, + editedResult: null, + }); + }; + + render(): React.ReactNode { + const { base64Image, editedResult, isLoading } = this.state; + const { selectedImage } = this.props; + + return ( + + + Test editPhoto (base64) + + + {selectedImage && ( +
+ Selected: {selectedImage.name} +
+ )} + + + {isLoading ? "Loading..." : "Load Selected Image as Base64"} + + + {base64Image && ( + <> + + Edit Photo (base64) + + + + Clear Photos + + +
+

Original Photo:

+ Original +
+ + )} + + {editedResult && ( +
+

Edited Photo:

+

+ Format: {editedResult.format} +

+ Edited +
+ )} +
+
+ ); + } +} + +export default EditPhotoConfigurable; diff --git a/example-app/src/components/camera/EditURIPhotoConfigurable.tsx b/example-app/src/components/camera/EditURIPhotoConfigurable.tsx new file mode 100644 index 0000000..15b768d --- /dev/null +++ b/example-app/src/components/camera/EditURIPhotoConfigurable.tsx @@ -0,0 +1,279 @@ +import { + IonButton, + IonCard, + IonCardContent, + IonCardHeader, + IonCardTitle, + IonItem, + IonLabel, + IonToggle, +} from "@ionic/react"; +import React from "react"; +import { Camera } from "@capacitor/camera"; +import { Filesystem, Directory } from "@capacitor/filesystem"; +import { Capacitor } from "@capacitor/core"; +import { TestImage } from "./TestImageData"; +import { MediaHistoryService } from "../../services/MediaHistoryService"; + +interface MediaResult { + path: string; + webPath: string; + duration?: number; + size: number; + format: string; + saved: boolean; +} + +interface EditURIPhotoConfig { + saveToGallery: boolean; + includeMetadata: boolean; +} + +interface EditURIPhotoConfigurableProps { + selectedImage: TestImage | null; +} + +interface EditURIPhotoConfigurableState { + savedFileUri: string | null; + savedFileWebPath: string | null; + editedPhoto: MediaResult | null; + config: EditURIPhotoConfig; + isLoading: boolean; +} + +class EditURIPhotoConfigurable extends React.Component< + EditURIPhotoConfigurableProps, + EditURIPhotoConfigurableState +> { + constructor(props: EditURIPhotoConfigurableProps) { + super(props); + this.state = { + savedFileUri: null, + savedFileWebPath: null, + editedPhoto: null, + config: { + saveToGallery: false, + includeMetadata: false, + }, + isLoading: false, + }; + } + + componentDidUpdate(prevProps: EditURIPhotoConfigurableProps): void { + if (this.props.selectedImage !== prevProps.selectedImage) { + this.setState({ + savedFileUri: null, + savedFileWebPath: null, + editedPhoto: null, + }); + } + } + + updateConfig = (field: keyof EditURIPhotoConfig, value: boolean): void => { + this.setState({ + config: { ...this.state.config, [field]: value }, + }); + }; + + saveImageToFile = async (): Promise => { + if (!this.props.selectedImage) { + alert("No image selected. Please select an image first."); + return; + } + + this.setState({ isLoading: true }); + + try { + const image = this.props.selectedImage; + let base64Data: string; + + if (image.type === "base64") { + base64Data = image.data; + } else { + // Fetch asset image and convert to base64 + const response = await fetch(image.data); + const blob = await response.blob(); + const base64String = await new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.onloadend = () => resolve(reader.result as string); + reader.onerror = reject; + reader.readAsDataURL(blob); + }); + // Remove the data:image/...;base64, prefix + base64Data = base64String.split(",")[1]; + } + + // Save to filesystem + const fileName = `test-image-${Date.now()}.png`; + const result = await Filesystem.writeFile({ + path: fileName, + data: base64Data, + directory: Directory.Cache, + }); + + // Get the file URI + const fileUri = result.uri; + const webPath = Capacitor.convertFileSrc(fileUri); + + this.setState({ + savedFileUri: fileUri, + savedFileWebPath: webPath, + editedPhoto: null, + isLoading: false, + }); + } catch (e) { + const error = e as any; + const errorMessage = error.code ? `[${error.code}] ${error.message}` : error.message; + alert(`Failed to save image to file with error:\n${errorMessage}`); + this.setState({ isLoading: false }); + } + }; + + editURIPhoto = async (): Promise => { + if (!this.state.savedFileUri) { + alert("No file saved. Please save the image to file first."); + return; + } + + try { + const result = await Camera.editURIPhoto({ + uri: this.state.savedFileUri, + saveToGallery: this.state.config.saveToGallery, + includeMetadata: this.state.config.includeMetadata, + }); + this.setState({ editedPhoto: result }); + + MediaHistoryService.addMedia({ + mediaType: "photo", + method: "editURIPhoto", + path: result.path, + webPath: result.webPath, + format: result.format, + size: result.size, + saved: result.saved, + }); + } catch (e) { + const error = e as any; + const errorMessage = error.code ? `[${error.code}] ${error.message}` : error.message; + alert(`Failed to edit photo with error:\n${errorMessage}`); + } + }; + + clearPhotos = (): void => { + this.setState({ + savedFileUri: null, + savedFileWebPath: null, + editedPhoto: null, + }); + }; + + render(): React.ReactNode { + const { savedFileUri, savedFileWebPath, editedPhoto, config, isLoading } = this.state; + const { selectedImage } = this.props; + + return ( + + + Test editURIPhoto + + + {selectedImage && ( +
+ Selected: {selectedImage.name} +
+ )} + + + {isLoading ? "Saving..." : "Save Selected Image to File"} + + + {savedFileUri && ( + <> +
+

Configuration:

+ + Save to Gallery + + this.updateConfig("saveToGallery", e.detail.checked) + } + /> + + + Include Metadata + + this.updateConfig("includeMetadata", e.detail.checked) + } + /> + +
+ + + Edit Photo (URI) + + + + Clear Photos + + +
+

Saved File:

+ Saved +

+ URI: {savedFileUri} +

+
+ + )} + + {editedPhoto && ( +
+

Edited Photo:

+ Edited +

+ Path: {editedPhoto.path} +

+

+ Size: {editedPhoto.size} bytes +

+

+ Format: {editedPhoto.format} +

+

+ Saved: {editedPhoto.saved ? "Yes" : "No"} +

+
+ )} +
+
+ ); + } +} + +export default EditURIPhotoConfigurable; diff --git a/example-app/src/components/camera/MediaCarousel.tsx b/example-app/src/components/camera/MediaCarousel.tsx new file mode 100644 index 0000000..6f57b5d --- /dev/null +++ b/example-app/src/components/camera/MediaCarousel.tsx @@ -0,0 +1,79 @@ +import React, { useState } from "react"; +import { GalleryPhoto } from "@capacitor/camera"; +import { Swiper, SwiperSlide } from "swiper/react"; +import { Navigation, Pagination } from "swiper/modules"; +import PhotoWithMetadata from "./PhotoWithMetadata"; +import VideoWithMetadata from "./VideoWithMetadata"; +import type { Swiper as SwiperType } from "swiper"; + +// Import Swiper styles +import "swiper/css"; +import "swiper/css/navigation"; +import "swiper/css/pagination"; + +interface IMediaCarouselProps { + // TODO change this type to allow including future MediaResult in ChooseFromGallery + media: GalleryPhoto[]; + onEditPhoto?: (filePath: string) => void; +} + +const MediaCarousel: React.FC = ({ media, onEditPhoto }) => { + const [currentIndex, setCurrentIndex] = useState(1); + + const handleSlideChange = (swiper: SwiperType) => { + setCurrentIndex(swiper.activeIndex + 1); + }; + + const isVideo = (format: string | undefined, filePath: string): boolean => { + const videoFormats = ['mp4', 'mov', 'avi', 'webm', 'mkv', 'm4v', 'flv']; + + // Check format first if available + if (format) { + return videoFormats.includes(format.toLowerCase()); + } + + // Fall back to checking file extension from path + const extension = filePath.split('.').pop()?.toLowerCase(); + return extension ? videoFormats.includes(extension) : false; + }; + + return ( +
+
+ Media {currentIndex}/{media.length} +
+ + {media.map((item, index) => { + const filePath = item.path ?? item.webPath; + const metadata = item.exif + ? JSON.stringify(item.exif, null, 2) + : null; + + return ( + + {isVideo(item.format, filePath) ? ( + + ) : ( + + )} + + ); + })} + +
+ ); +}; + +export default MediaCarousel; diff --git a/example-app/src/components/camera/PhotoWithMetadata.tsx b/example-app/src/components/camera/PhotoWithMetadata.tsx new file mode 100644 index 0000000..d7e1998 --- /dev/null +++ b/example-app/src/components/camera/PhotoWithMetadata.tsx @@ -0,0 +1,42 @@ +import React from "react"; +import { IonCard, IonCardContent, IonButton } from "@ionic/react"; +import { Capacitor } from "@capacitor/core"; + +interface IPhotoWithMetadataProps { + filePath: string; + metadata?: string | null; + onEdit?: (filePath: string) => void; +} + +const PhotoWithMetadata: React.FC = ({ + filePath, + metadata, + onEdit, +}) => { + return ( + + +
+ Captured +
+ {onEdit && ( + onEdit(filePath)} + style={{ marginTop: "8px" }} + > + Edit This Photo + + )} + {metadata && ( +
+
{metadata}
+
+ )} +
+
+ ); +}; + +export default PhotoWithMetadata; diff --git a/example-app/src/components/camera/RecordVideoConfigurable.tsx b/example-app/src/components/camera/RecordVideoConfigurable.tsx new file mode 100644 index 0000000..b7c8d81 --- /dev/null +++ b/example-app/src/components/camera/RecordVideoConfigurable.tsx @@ -0,0 +1,140 @@ +import { + IonButton, + IonAccordion, + IonAccordionGroup, + IonItem, + IonLabel, + IonToggle, +} from "@ionic/react"; +import React from "react"; +import { Camera } from "@capacitor/camera"; + +interface RecordVideoConfig { + saveToGallery: boolean; + includeMetadata: boolean; +} + +interface VideoResult { + path: string; + webPath: string; + duration?: number; + size: number; + format: string; + saved: boolean; +} + +interface RecordVideoConfigurableProps { + buttonLabel?: string; + onVideoResult: (result: VideoResult) => void; +} + +interface RecordVideoConfigurableState { + config: RecordVideoConfig; +} + +class RecordVideoConfigurable extends React.Component< + RecordVideoConfigurableProps, + RecordVideoConfigurableState +> { + constructor(props: RecordVideoConfigurableProps) { + super(props); + this.state = { + config: { + saveToGallery: false, + includeMetadata: true, + }, + }; + } + + updateConfig = (field: keyof RecordVideoConfig, value: any): void => { + this.setState({ + config: { ...this.state.config, [field]: value }, + }); + }; + + executeDefault = async (): Promise => { + try { + const result = await Camera.recordVideo({}); + this.props.onVideoResult(result); + } catch (e) { + const error = e as any; + const errorMessage = error.code ? `[${error.code}] ${error.message}` : error.message; + alert(`Failed to record video with error:\n${errorMessage}`); + } + }; + + executeWithConfig = async (): Promise => { + try { + const config = this.state.config; + const result = await Camera.recordVideo({ + saveToGallery: config.saveToGallery, + includeMetadata: config.includeMetadata, + }); + this.props.onVideoResult(result); + } catch (e) { + const error = e as any; + const errorMessage = error.code ? `[${error.code}] ${error.message}` : error.message; + alert(`Failed to record video with error:\n${errorMessage}`); + } + }; + + render() { + const { buttonLabel = "recordVideo (Default)" } = this.props; + const { config } = this.state; + + return ( + <> + this.executeDefault()}> + {buttonLabel} + + + + + + + Expand to call recordVideo with configurable options + + +
+ + Save to Gallery + + this.updateConfig("saveToGallery", e.detail.checked) + } + /> + + + + Include Metadata + + this.updateConfig("includeMetadata", e.detail.checked) + } + /> + + + this.executeWithConfig()} + > + Execute recordVideo with Configuration + +
+
+
+ + ); + } +} + +export default RecordVideoConfigurable; diff --git a/example-app/src/components/camera/TakePictureConfigurable.tsx b/example-app/src/components/camera/TakePictureConfigurable.tsx new file mode 100644 index 0000000..7d46382 --- /dev/null +++ b/example-app/src/components/camera/TakePictureConfigurable.tsx @@ -0,0 +1,284 @@ +import { + IonButton, + IonAccordion, + IonAccordionGroup, + IonItem, + IonLabel, + IonInput, + IonSelect, + IonSelectOption, + IonToggle, +} from "@ionic/react"; +import React from "react"; +import { + Camera, + ImageOptions, + CameraResultType, + CameraDirection, +} from "@capacitor/camera"; + +interface TakePictureConfig { + quality: number; + allowEditing: boolean; + resultType: CameraResultType; + saveToGallery: boolean; + width: number | undefined; + height: number | undefined; + correctOrientation: boolean; + direction: CameraDirection; + presentationStyle: 'fullscreen' | 'popover'; +} + +interface PhotoResult { + path: string; + webPath: string; + duration?: number; + size: number; + format: string; + saved: boolean; +} + +interface TakePictureConfigurableProps { + buttonLabel?: string; + onPhotoResult: (result: PhotoResult) => void; +} + +interface TakePictureConfigurableState { + config: TakePictureConfig; +} + +class TakePictureConfigurable extends React.Component< + TakePictureConfigurableProps, + TakePictureConfigurableState +> { + constructor(props: TakePictureConfigurableProps) { + super(props); + this.state = { + config: { + quality: 100, + allowEditing: false, + resultType: CameraResultType.Uri, // TODO confirm if we want this in the new API? + saveToGallery: false, + width: undefined, + height: undefined, + correctOrientation: true, + direction: CameraDirection.Rear, + presentationStyle: 'fullscreen', + }, + }; + } + + updateConfig = (field: keyof TakePictureConfig, value: any): void => { + this.setState({ + config: { ...this.state.config, [field]: value }, + }); + }; + + executeDefault = async (): Promise => { + try { + const options: ImageOptions = { + resultType: CameraResultType.Uri, + }; + const result = await Camera.takePhoto(options); + this.props.onPhotoResult(result); + } catch (e) { + const error = e as any; + const errorMessage = error.code ? `[${error.code}] ${error.message}` : error.message; + alert(`Failed to take picture with error:\n${errorMessage}`); + } + }; + + executeWithConfig = async (): Promise => { + try { + const config = this.state.config; + const options: ImageOptions = { + quality: config.quality, + allowEditing: config.allowEditing, + resultType: config.resultType, + saveToGallery: config.saveToGallery, + width: config.width, + height: config.height, + correctOrientation: config.correctOrientation, + direction: config.direction, + presentationStyle: config.presentationStyle, + }; + const result = await Camera.takePhoto(options); + this.props.onPhotoResult(result); + } catch (e) { + const error = e as any; + const errorMessage = error.code ? `[${error.code}] ${error.message}` : error.message; + alert(`Failed to take picture with error:\n${errorMessage}`); + } + }; + + render() { + const { buttonLabel = "takePhoto (Default)" } = this.props; + const { config } = this.state; + + return ( + <> + this.executeDefault()}> + {buttonLabel} + + + + + + + Expand to call takePhoto with configurable options + + +
+ {/* Core settings */} + + Quality (0-100) + + this.updateConfig("quality", parseInt(e.detail.value!) || 100) + } + /> + + + + Result Type + + this.updateConfig("resultType", e.detail.value) + } + > + + Uri + + + Base64 + + + DataUrl + + + + + {/* Platform-specific */} + + Direction (iOS) + + this.updateConfig("direction", e.detail.value) + } + > + + Rear + + + Front + + + + + + + Presentation Style (iOS) + + + this.updateConfig("presentationStyle", e.detail.value) + } + > + + Fullscreen + + Popover + + + + {/* Dimensions */} + + Width (optional) + + this.updateConfig( + "width", + e.detail.value ? parseInt(e.detail.value) : undefined + ) + } + /> + + + + Height (optional) + + this.updateConfig( + "height", + e.detail.value ? parseInt(e.detail.value) : undefined + ) + } + /> + + + {/* Boolean toggles */} + + Allow Editing + + this.updateConfig("allowEditing", e.detail.checked) + } + /> + + + + Save to Gallery + + this.updateConfig("saveToGallery", e.detail.checked) + } + /> + + + + Correct Orientation + + this.updateConfig("correctOrientation", e.detail.checked) + } + /> + + + this.executeWithConfig()} + > + Execute takePhoto with Configuration + +
+
+
+ + ); + } +} + +export default TakePictureConfigurable; diff --git a/example-app/src/components/camera/TestImageData.ts b/example-app/src/components/camera/TestImageData.ts new file mode 100644 index 0000000..7ddf175 --- /dev/null +++ b/example-app/src/components/camera/TestImageData.ts @@ -0,0 +1,50 @@ +// Test images for Edit Photo functionality +// Small base64 encoded images for testing + +export interface TestImage { + id: string; + name: string; + type: "base64" | "asset"; + data: string; // base64 string or asset path +} + +// Squared image with colored squares (1024x1024 PNG) +const SQUARED_IMAGE_BASE64 = + "iVBORw0KGgoAAAANSUhEUgAABAAAAAQACAIAAADwf7zUAAAb6UlEQVR4nOzZexP3dV3ncS65rl1WFFkHT4uKyyK7eARdmHVRPK1ysWlQHsAmMRMbElFAMwTzRFx4QEAD84iiRgKK2AFEbSAlS8QsHRAUBMRSMtAETASz2+B8ZnoP83w8bsHrj+/8fvP8vDd+YtcDt7or2/rKHaYnLDn40D+ZnrDk5B9ump6w5C9ftO30hCV/dfh50xOWfOpFfzc9Yckul311esKSk856+vSEJRdf/57pCUuuesnR0xOW7Hfka6cnLNnmrXtPT1hy7u5/Nj1hyWkH3bW/n1fe9x3TE5bcbXoAAADwH0cAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACNlwzTU/md6w5GnHvXt6wpJTL3zu9IQlf//8G6cnLNntIQdOT1iyw4lbpics2XLzDdMTljzxY4dOT1jyst2eOj1hyRv+3wnTE5Y85NPHTk9YctZt35iesOQHn3zK9IQlt9z5sekJS35+9remJyx54XGbpycscQEAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBkw47f3Xp6w5Kz//mm6QlLdvrw0dMTlhz//k3TE5Ycc+GF0xOW3PCC+01PWPKqre49PWHJwR+9enrCki/9+NrpCUvedenrpicsuebCm6cnLNmw1YnTE5a85lmXTk9Y8qQv3LXfcI94xgOmJyzZ9uRTpicsuWt/PQAAwC9EAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAjZ8BdHbTe9YclZj3ru9IQln/+lV09PWLLXmf9/esKST/38w9MTlpz5lK9NT1hy7P6XT09YcsWHT5uesOSQ7zx/esKSkw5+xfSEJbf9dP/pCUvuedPm6QlL/vSc/aYnLPn2U4+bnrDk9mPfPT1hyS2Pfvj0hCUuAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhGzc6QM7Tm9Y8ra/3m16wpLL//by6QlLNrz4zukJS+7xzO9MT1hyj3deMT1hyWEXPGR6wpLfef0jpicsuXXbg6YnLLntfYdMT1hy9KZvTU9Ycv65P5yesGSH9z5vesKSx//Xc6cnLNnnK++fnrBk/8/ea3rCEhcAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCNm5+xKumNyx51C0nT09Yssf2109PWPLHx985PWHJvTdfOT1hydHn7Ts9Ycnhb/z69IQlLzv6e9MTlmzzxAumJyx5+Gtvmp6w5Gn333Z6wpIH3nO76QlL3v7E+05PWPI3L3jO9IQlj7nkLdMTlvzLtY+dnrDEBQAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgJAND93tCdMblrx7172nJyy55Oqrpics2XS/n0xPWHLPW7eenrDk9A/tNT1hyWvv/ML0hCXnX/+Z6QlLnnrH26YnLNnmPpunJyy5/rMvn56w5IptPz09Ycl+b/rh9IQl+z7229MTllz1ki9OT1jyuRdvmZ6wxAUAAABCBAAAAIQIAAAACBEAAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAICQjWdftcv0hiXn7rZlesKSH+z6oekJS7645x7TE5a888jPTU9Ycv+f//L0hCWP+8J10xOWbNr+1dMTljzr9FdMT1hy6KWXT09Ycuk+N05PWPLgVxw1PWHJ4XdsMz1hyYZDfjY9YckD3/WR6QlLtn/pO6YnLHEBAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgZMNOX919esOST5x6+/SEJZd8/CvTE5Zsfck10xOW/N4zPzA9Ycnvn3319IQlXzrorv0G8Z++ccz0hCWvP/v/TE9YsstWz5iesOSG7503PWHJZZuump6w5EGf3Ht6wpIf73Hz9IQl29xt5+kJSw7f/bLpCUvu2v++AADAL0QAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACNn4hB2PmN6w5JrfPmp6wpLNm0+ZnrBky1cOmJ6w5KprL5qesOTH59xnesKSex32P6cnLDnnoe+YnrBkr2P+9/SEJYedcOv0hCX//aOHTk9Ycumf7zs9Ycnu/2W76QlLjv9v75+esOTjF719esKSR+907fSEJS4AAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACEbDjqN/af3rDkble+fXrCkn/Y+pvTE5bs/rBjpicseeE3t0xPWPKAHc+cnrDkze87ZHrCkgN2fcv0hCVnnPnK6QlLzj/x9ukJS4742tumJyy5YK/PT09Y8k8HXj89YcmRZ+wwPWHJl1/67OkJS/Z5/S3TE5a4AAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAELLx6Bs+Mr1hyU4fvGF6wpJn7b3j9IQl2/3gg9MTlux582enJyx53gs+Mz1hyfmPvXl6wpLbD3jT9IQl/3b3l0xPWPKm708vWHPL166cnrDkrH3uPT1hyeXHHzk9YcnON+06PWHJp775P6YnLLn7aVdMT1jiAgAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBEAAAAQMjGIy44cHrDkl974TbTE5b87pcPnZ6w5K3/90HTE5act993pycs2fOyE6cnLDnvSb85PWHJGSf/0fSEJTs84V+nJyx57h2PmZ6w5DkfumJ6wpLv3/pb0xOW7LDH1dMTlvzno2+cnrDkoOufPD1hyYPvOGh6whIXAAAACBEAAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQjaeev2npzcsufoRz5iesOSVN54/PWHJLi964PSEJR/Y85TpCUt+dPhnpicsufQNt05PWHLbcS+enrBk93P+cHrCkovu2Hl6wpL9t+w7PWHJ9je8d3rCkh0P++r0hCWP2/ie6QlLNj368dMTllx33anTE5a4AAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAELLhJ6f/4/SGJaeff930hCV7Pmzn6QlL3nj4rdMTllx3wvnTE5Y8+1dPmJ6w5PKTDpiesOSAzadNT1jyzItOnJ6w5KRHHjY9YcmFj/yV6QlLnvK/jp2esGSnp399esKSx9/50OkJS7bs8ezpCUsufs1bpycscQEAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBkw76POW16w5INmw6enrDksjOOnZ6w5B7bv2F6wpJdLn749IQl77v/H0xPWPLki987PWHJ606/cHrCkpef9LLpCUs+d+Rd+/fnoNOunJ6w5M03HzY9Yckpv77P9IQlezzuXdMTluz1o59NT1jyvYf9dHrCEhcAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABCBAAAAIQIAAAACBEAAAAQIgAAACBEAAAAQIgAAACAEAEAAAAhAgAAAEIEAAAAhAgAAAAIEQAAABAiAAAAIEQAAABAiAAAAIAQAQAAACECAAAAQgQAAACECAAAAAgRAAAAECIAAAAgRAAAAECIAAAAgBABAAAAIQIAAABC/j0AAP//sQyHNMzZwyAAAAAASUVORK5CYII="; + +// Small gradient test image (512x512 PNG) +const GRADIENT_BASE64 = + "iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAIAAADTED8xAAADMElEQVR4nOzVwQnAIBQFQYXff81RUkQCOyDj1YOPnbXWPmeTRef+/3O/OyBjzh3CD95BfqICMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMO0TAAD//2Anhf4QtqobAAAAAElFTkSuQmCC"; + +export const TEST_IMAGES: TestImage[] = [ + { + id: "squared", + name: "Squared (base64)", + type: "base64", + data: SQUARED_IMAGE_BASE64, + }, + { + id: "gradient", + name: "Gradient (base64)", + type: "base64", + data: GRADIENT_BASE64, + }, + { + id: "favicon", + name: "Favicon (asset)", + type: "asset", + data: "/favicon.png", + }, + { + id: "flower-jpg", + name: "Flower JPG (asset)", + type: "asset", + data: "/flower.jpg", + }, + { + id: "capacitor-png", + name: "Capacitor Transparent BG (asset)", + type: "asset", + data: "/capacitorjs.png", + }, +]; diff --git a/example-app/src/components/camera/TestImageSelector.tsx b/example-app/src/components/camera/TestImageSelector.tsx new file mode 100644 index 0000000..6e44e03 --- /dev/null +++ b/example-app/src/components/camera/TestImageSelector.tsx @@ -0,0 +1,84 @@ +import React, { useState, useEffect } from "react"; +import { IonCard, IonCardContent, IonCardHeader, IonCardTitle } from "@ionic/react"; +import { Swiper, SwiperSlide } from "swiper/react"; +import { Navigation, Pagination } from "swiper/modules"; +import type { Swiper as SwiperType } from "swiper"; +import { TEST_IMAGES, TestImage } from "./TestImageData"; + +import "swiper/css"; +import "swiper/css/navigation"; +import "swiper/css/pagination"; + +interface TestImageSelectorProps { + onImageSelected: (image: TestImage) => void; +} + +const TestImageSelector: React.FC = ({ onImageSelected }) => { + const [currentIndex, setCurrentIndex] = useState(0); + + useEffect(() => { + onImageSelected(TEST_IMAGES[0]); + }, []); + + const handleSlideChange = (swiper: SwiperType): void => { + const index = swiper.activeIndex; + setCurrentIndex(index); + onImageSelected(TEST_IMAGES[index]); + }; + + const getImageSrc = (image: TestImage): string => { + if (image.type === "base64") { + return `data:image/png;base64,${image.data}`; + } + return image.data; + }; + + return ( + + + Select Test Image + + +
+ {currentIndex + 1}/{TEST_IMAGES.length} - {TEST_IMAGES[currentIndex].name} +
+ + {TEST_IMAGES.map((image, index) => ( + +
+ {image.name} +
+
+ ))} +
+
+
+ ); +}; + +export default TestImageSelector; diff --git a/example-app/src/components/camera/VideoWithMetadata.tsx b/example-app/src/components/camera/VideoWithMetadata.tsx new file mode 100644 index 0000000..092592d --- /dev/null +++ b/example-app/src/components/camera/VideoWithMetadata.tsx @@ -0,0 +1,34 @@ +import React from "react"; +import { IonCard, IonCardContent } from "@ionic/react"; +import { Capacitor } from "@capacitor/core"; + +interface IVideoWithMetadataProps { + filePath: string; + metadata?: string | null; +} + +const VideoWithMetadata: React.FC = ({ + filePath, + metadata, +}) => { + return ( + + +
+
+ {metadata && ( +
+
{metadata}
+
+ )} +
+
+ ); +}; + +export default VideoWithMetadata; diff --git a/example-app/src/components/camera/old-methods/GetPhotoConfigurable.tsx b/example-app/src/components/camera/old-methods/GetPhotoConfigurable.tsx new file mode 100644 index 0000000..af4cc66 --- /dev/null +++ b/example-app/src/components/camera/old-methods/GetPhotoConfigurable.tsx @@ -0,0 +1,372 @@ +import { + IonButton, + IonAccordion, + IonAccordionGroup, + IonItem, + IonLabel, + IonInput, + IonSelect, + IonSelectOption, + IonToggle, +} from "@ionic/react"; +import React from "react"; +import { + Camera, + ImageOptions, + CameraSource, + CameraResultType, + CameraDirection, +} from "@capacitor/camera"; +import { GetPhotoConfig, PhotoResult } from "./types"; + +interface GetPhotoConfigurableProps { + buttonLabel?: string; + defaultSource?: CameraSource; + defaultWebUseInput?: boolean; + onPhotoResult: (result: PhotoResult) => void; +} + +interface GetPhotoConfigurableState { + config: GetPhotoConfig; +} + +class GetPhotoConfigurable extends React.Component< + GetPhotoConfigurableProps, + GetPhotoConfigurableState +> { + constructor(props: GetPhotoConfigurableProps) { + super(props); + this.state = { + config: { + quality: 100, + allowEditing: false, + resultType: CameraResultType.Uri, + source: props.defaultSource ?? CameraSource.Prompt, + saveToGallery: false, + width: undefined, + height: undefined, + correctOrientation: true, + direction: CameraDirection.Rear, + presentationStyle: 'fullscreen', + webUseInput: props.defaultWebUseInput ?? false, + promptLabelHeader: 'Photo', + promptLabelCancel: 'Cancel', + promptLabelPhoto: 'From Photos', + promptLabelPicture: 'Take Picture', + }, + }; + } + + updateConfig = (field: keyof GetPhotoConfig, value: any): void => { + this.setState({ + config: { ...this.state.config, [field]: value }, + }); + }; + + executeDefault = async (): Promise => { + try { + const options: ImageOptions = { + resultType: CameraResultType.Uri, + }; + const photo = await Camera.getPhoto(options); + this.props.onPhotoResult({ + path: photo.path, + webPath: photo.webPath, + exif: photo.exif, + }); + } catch (e) { + const error = e as any; + const errorMessage = error.code ? `[${error.code}] ${error.message}` : error.message; + alert(`Failed to get picture with error:\n${errorMessage}`); + } + }; + + executeWithConfig = async (): Promise => { + try { + const config = this.state.config; + const options: ImageOptions = { + quality: config.quality, + allowEditing: config.allowEditing, + resultType: config.resultType, + source: config.source, + saveToGallery: config.saveToGallery, + width: config.width, + height: config.height, + correctOrientation: config.correctOrientation, + direction: config.direction, + presentationStyle: config.presentationStyle, + webUseInput: config.webUseInput, + promptLabelHeader: config.promptLabelHeader, + promptLabelCancel: config.promptLabelCancel, + promptLabelPhoto: config.promptLabelPhoto, + promptLabelPicture: config.promptLabelPicture, + }; + const photo = await Camera.getPhoto(options); + this.props.onPhotoResult({ + path: photo.path, + webPath: photo.webPath, + exif: photo.exif, + }); + } catch (e) { + const error = e as any; + const errorMessage = error.code ? `[${error.code}] ${error.message}` : error.message; + alert(`Failed to get picture with error:\n${errorMessage}`); + } + }; + + render() { + const { buttonLabel = "getPhoto (Default)" } = this.props; + const { config } = this.state; + + return ( + <> + this.executeDefault()}> + {buttonLabel} + + + + + + + Expand to call getPhoto with configurable options + + +
+ {/* Core settings */} + + Quality (0-100) + + this.updateConfig("quality", parseInt(e.detail.value!) || 100) + } + /> + + + + Result Type + + this.updateConfig("resultType", e.detail.value) + } + > + + Uri + + + Base64 + + + DataUrl + + + + + + Source + this.updateConfig("source", e.detail.value)} + > + + Prompt + + + Camera + + + Photos + + + + + {/* Platform-specific */} + + Direction (iOS) + + this.updateConfig("direction", e.detail.value) + } + > + + Rear + + + Front + + + + + + + Presentation Style (iOS) + + + this.updateConfig("presentationStyle", e.detail.value) + } + > + + Fullscreen + + Popover + + + + {/* Dimensions */} + + Width (optional) + + this.updateConfig( + "width", + e.detail.value ? parseInt(e.detail.value) : undefined + ) + } + /> + + + + Height (optional) + + this.updateConfig( + "height", + e.detail.value ? parseInt(e.detail.value) : undefined + ) + } + /> + + + {/* Boolean toggles */} + + Allow Editing + + this.updateConfig("allowEditing", e.detail.checked) + } + /> + + + + Save to Gallery + + this.updateConfig("saveToGallery", e.detail.checked) + } + /> + + + + Correct Orientation + + this.updateConfig("correctOrientation", e.detail.checked) + } + /> + + + + Web Use Input + + this.updateConfig("webUseInput", e.detail.checked) + } + /> + + + {/* Text customizations */} + + Prompt Label Header + + this.updateConfig( + "promptLabelHeader", + e.detail.value ?? "Photo" + ) + } + /> + + + + Prompt Label Cancel + + this.updateConfig( + "promptLabelCancel", + e.detail.value ?? "Cancel" + ) + } + /> + + + + Prompt Label Photo + + this.updateConfig( + "promptLabelPhoto", + e.detail.value ?? "From Photos" + ) + } + /> + + + + Prompt Label Picture + + this.updateConfig( + "promptLabelPicture", + e.detail.value ?? "Take Picture" + ) + } + /> + + + this.executeWithConfig()} + > + Execute getPhoto with Configuration + +
+
+
+ + ); + } +} + +export default GetPhotoConfigurable; diff --git a/example-app/src/components/camera/old-methods/PickImagesConfigurable.tsx b/example-app/src/components/camera/old-methods/PickImagesConfigurable.tsx new file mode 100644 index 0000000..bfc02b2 --- /dev/null +++ b/example-app/src/components/camera/old-methods/PickImagesConfigurable.tsx @@ -0,0 +1,213 @@ +import { + IonButton, + IonAccordion, + IonAccordionGroup, + IonItem, + IonLabel, + IonInput, + IonSelect, + IonSelectOption, + IonToggle, +} from "@ionic/react"; +import React from "react"; +import { + Camera, + GalleryImageOptions, + GalleryPhoto, +} from "@capacitor/camera"; +import { PickImagesConfig } from "./types"; + +interface PickImagesConfigurableProps { + buttonLabel?: string; + onPhotosResult: (photos: GalleryPhoto[]) => void; +} + +interface PickImagesConfigurableState { + config: PickImagesConfig; +} + +class PickImagesConfigurable extends React.Component< + PickImagesConfigurableProps, + PickImagesConfigurableState +> { + constructor(props: PickImagesConfigurableProps) { + super(props); + this.state = { + config: { + quality: 100, + width: undefined, + height: undefined, + correctOrientation: true, + presentationStyle: 'fullscreen', + limit: 0, + }, + }; + } + + updateConfig = (field: keyof PickImagesConfig, value: any): void => { + this.setState({ + config: { ...this.state.config, [field]: value }, + }); + }; + + executeDefault = async (): Promise => { + try { + const photosResult = await Camera.pickImages({}); + console.log("photos result", photosResult); + this.props.onPhotosResult(photosResult.photos); + } catch (e) { + const error = e as any; + const errorMessage = error.code ? `[${error.code}] ${error.message}` : error.message; + alert(`Failed to pick images with error:\n${errorMessage}`); + } + }; + + executeWithConfig = async (): Promise => { + try { + const config = this.state.config; + const options: GalleryImageOptions = { + quality: config.quality, + width: config.width, + height: config.height, + correctOrientation: config.correctOrientation, + presentationStyle: config.presentationStyle, + limit: config.limit, + }; + const photosResult = await Camera.pickImages(options); + console.log("photos result", photosResult); + this.props.onPhotosResult(photosResult.photos); + } catch (e) { + const error = e as any; + const errorMessage = error.code ? `[${error.code}] ${error.message}` : error.message; + alert(`Failed to pick images with error:\n${errorMessage}`); + } + }; + + render() { + const { buttonLabel = "pickImages (Default)" } = this.props; + const { config } = this.state; + + return ( + <> + this.executeDefault()} + style={{ marginTop: "16px" }} + > + {buttonLabel} + + + + + + + Expand to call pickImages with configurable options + + +
+ + Quality (0-100) + + this.updateConfig("quality", parseInt(e.detail.value!) || 100) + } + /> + + + + Width (optional) + + this.updateConfig( + "width", + e.detail.value ? parseInt(e.detail.value) : undefined + ) + } + /> + + + + Height (optional) + + this.updateConfig( + "height", + e.detail.value ? parseInt(e.detail.value) : undefined + ) + } + /> + + + + + Limit (0 = unlimited, Android 13+ & iOS) + + + this.updateConfig("limit", parseInt(e.detail.value!) || 0) + } + /> + + + + + Presentation Style (iOS) + + + this.updateConfig("presentationStyle", e.detail.value) + } + > + + Fullscreen + + Popover + + + + + Correct Orientation + + this.updateConfig("correctOrientation", e.detail.checked) + } + /> + + + this.executeWithConfig()} + > + Execute pickImages with Configuration + +
+
+
+ + ); + } +} + +export default PickImagesConfigurable; diff --git a/example-app/src/components/camera/old-methods/index.ts b/example-app/src/components/camera/old-methods/index.ts new file mode 100644 index 0000000..1bc919c --- /dev/null +++ b/example-app/src/components/camera/old-methods/index.ts @@ -0,0 +1,3 @@ +export { default as GetPhotoConfigurable } from "./GetPhotoConfigurable"; +export { default as PickImagesConfigurable } from "./PickImagesConfigurable"; +export * from "./types"; diff --git a/example-app/src/components/camera/old-methods/types.ts b/example-app/src/components/camera/old-methods/types.ts new file mode 100644 index 0000000..cddd3b0 --- /dev/null +++ b/example-app/src/components/camera/old-methods/types.ts @@ -0,0 +1,34 @@ +import { CameraResultType, CameraSource, CameraDirection } from "@capacitor/camera"; + +export interface GetPhotoConfig { + quality: number; + allowEditing: boolean; + resultType: CameraResultType; + source: CameraSource; + saveToGallery: boolean; + width: number | undefined; + height: number | undefined; + correctOrientation: boolean; + direction: CameraDirection; + presentationStyle: 'fullscreen' | 'popover'; + webUseInput: boolean; + promptLabelHeader: string; + promptLabelCancel: string; + promptLabelPhoto: string; + promptLabelPicture: string; +} + +export interface PickImagesConfig { + quality: number; + width: number | undefined; + height: number | undefined; + correctOrientation: boolean; + presentationStyle: 'fullscreen' | 'popover'; + limit: number; +} + +export interface PhotoResult { + path?: string; + webPath?: string; + exif?: any; +} diff --git a/example-app/src/pages/Camera.css b/example-app/src/pages/Camera.css deleted file mode 100644 index 8b13789..0000000 --- a/example-app/src/pages/Camera.css +++ /dev/null @@ -1 +0,0 @@ - diff --git a/example-app/src/pages/Camera.tsx b/example-app/src/pages/Camera.tsx deleted file mode 100644 index 7e4a134..0000000 --- a/example-app/src/pages/Camera.tsx +++ /dev/null @@ -1,232 +0,0 @@ -import { - IonButtons, - IonContent, - IonHeader, - IonPage, - IonMenuButton, - IonTitle, - IonToolbar, - IonCardContent, - IonCard, - IonButton, - IonGrid, - IonRow, - IonCol, - IonImg, -} from '@ionic/react'; -import './Camera.css'; -import React from 'react'; -import { - Camera, - ImageOptions, - CameraSource, - CameraResultType, - CameraPluginPermissions, - GalleryPhoto, - GalleryImageOptions, -} from '@capacitor/camera'; -import { Capacitor } from '@capacitor/core'; - -interface CameraPageState { - filePath: string | null; - metadata: string | null; - photos: GalleryPhoto[] | null; -} - -class CameraPage extends React.Component<{}, CameraPageState> { - constructor(props: {}) { - super(props); - this.state = { filePath: null, metadata: null, photos: null }; - } - - addPhoto = async ( - source: CameraSource, - save: boolean = false, - editing: boolean = false, - ) => { - try { - const options: ImageOptions = { - quality: 100, - resultType: CameraResultType.Uri, - source: source, - saveToGallery: save, - allowEditing: editing, - webUseInput: source === CameraSource.Photos, - }; - var photo = await Camera.getPhoto(options); - this.setState({ - filePath: photo.path ?? photo.webPath ?? null, - metadata: JSON.stringify(photo.exif, null, 2), - }); - } catch (e) { - alert(`Failed to get picture with error:\n'${e}'`); - } - }; - - pickPhotos = async (limit: number = 0) => { - try { - const options: GalleryImageOptions = { - quality: 100, - limit, - }; - var photosResult = await Camera.pickImages(options); - console.log('photos result', photosResult); - this.setState({ - photos: photosResult.photos, - }); - } catch (e) { - alert(`Failed to get picture with error:\n'${e}'`); - } - }; - - checkPermissions = async () => { - const permissionStates = await Camera.checkPermissions(); - alert( - `Permissions are:\ncamera = ${permissionStates.camera}\nphotos = ${permissionStates.photos}`, - ); - }; - - requestPermissions = async (permissions?: CameraPluginPermissions) => { - const permissionStates = await Camera.requestPermissions(permissions); - alert( - `Permissions are:\ncamera = ${permissionStates.camera}\nphotos = ${permissionStates.photos}`, - ); - }; - - pickLimitedLibraryPhotos = async () => { - const res = await Camera.pickLimitedLibraryPhotos(); - console.log('res', res); - }; - - getLimitedLibraryPhotos = async () => { - const res = await Camera.getLimitedLibraryPhotos(); - console.log('res', res); - }; - - render() { - const photos = this.state.photos; - return ( - - - - - - - Camera - - - - - - this.checkPermissions()}> - Check Permissions - - - this.requestPermissions({ permissions: ['camera'] }) - } - > - Request Camera Permissions - - - this.requestPermissions({ permissions: ['photos'] }) - } - > - Request Photo Permissions - - this.requestPermissions()} - > - Request All Permissions - - - - - - this.addPhoto(CameraSource.Camera)} - > - Take Picture - - this.addPhoto(CameraSource.Camera, true)} - > - Take Picture and Save - - this.addPhoto(CameraSource.Camera, false, true)} - > - Take Picture and Edit - - this.addPhoto(CameraSource.Photos)} - > - Choose Picture - - this.addPhoto(CameraSource.Prompt)} - > - Prompt - - this.pickPhotos()}> - Pick Photos - - this.pickPhotos(3)}> - Pick 3 Photos - - this.pickLimitedLibraryPhotos()} - > - pickLimitedLibraryPhotos - - this.getLimitedLibraryPhotos()} - > - getLimitedLibraryPhotos - - - - - - {photos?.map(photo => ( - - - - ))} - - - {this.state.filePath != null ? ( - - -
- Most Recent -
-
-
{this.state.metadata}
-
-
-
- ) : ( -
- )} -
-
- ); - } -} - -export default CameraPage; diff --git a/example-app/src/pages/EditPhotoPage.tsx b/example-app/src/pages/EditPhotoPage.tsx new file mode 100644 index 0000000..f218d31 --- /dev/null +++ b/example-app/src/pages/EditPhotoPage.tsx @@ -0,0 +1,51 @@ +import { + IonButtons, + IonContent, + IonHeader, + IonPage, + IonMenuButton, + IonTitle, + IonToolbar, +} from "@ionic/react"; +import React, { useState } from "react"; +import TestImageSelector from "../components/camera/TestImageSelector"; +import EditPhotoConfigurable from "../components/camera/EditPhotoConfigurable"; +import EditURIPhotoConfigurable from "../components/camera/EditURIPhotoConfigurable"; +import { TestImage } from "../components/camera/TestImageData"; + +const EditPhotoPage: React.FC = () => { + const [selectedImage, setSelectedImage] = useState(null); + + const handleImageSelected = (image: TestImage): void => { + setSelectedImage(image); + }; + + return ( + + + + + + + Edit Photo + + + +
+

+ This page tests Edit methods (editPhoto and editURIPhoto) in isolation using pre-loaded test images. +

+

+ To test Edit methods with Camera/Gallery workflows, visit the Take Picture or Gallery pages. +

+
+ + + +
+ + + ); +}; + +export default EditPhotoPage; diff --git a/example-app/src/pages/GalleryPage.tsx b/example-app/src/pages/GalleryPage.tsx new file mode 100644 index 0000000..f12aedb --- /dev/null +++ b/example-app/src/pages/GalleryPage.tsx @@ -0,0 +1,267 @@ +import { + IonButtons, + IonContent, + IonHeader, + IonPage, + IonMenuButton, + IonTitle, + IonToolbar, + IonCardContent, + IonCard, + IonAccordion, + IonAccordionGroup, + IonItem, + IonLabel, + IonButton, +} from "@ionic/react"; +import React from "react"; +import { + Camera, + CameraSource, + GalleryPhoto, +} from "@capacitor/camera"; +import PhotoWithMetadata from "../components/camera/PhotoWithMetadata"; +import MediaCarousel from "../components/camera/MediaCarousel"; +import ChooseFromGalleryConfigurable from "../components/camera/ChooseFromGalleryConfigurable"; +import { + GetPhotoConfigurable, + PickImagesConfigurable, +} from "../components/camera/old-methods"; +import { MediaHistoryService } from "../services/MediaHistoryService"; + +interface MediaResult { + path: string; + webPath: string; + duration?: number; + size: number; + format: string; + saved: boolean; +} + +interface IGalleryPageState { + singlePhoto: { + filePath: string | null; + metadata: string | null; + } | null; + multiplePhotos: GalleryPhoto[] | null; + editedPhoto: MediaResult | null; +} + +class GalleryPage extends React.Component<{}, IGalleryPageState> { + constructor(props: {}) { + super(props); + this.state = { + singlePhoto: null, + multiplePhotos: null, + editedPhoto: null, + }; + } + + handlePhotoResult = (result: { + path?: string; + webPath?: string; + exif?: any; + }): void => { + this.setState({ + singlePhoto: { + filePath: result.path ?? result.webPath ?? null, + metadata: JSON.stringify(result.exif, null, 2), + }, + multiplePhotos: null, + }); + + if (result.path || result.webPath) { + MediaHistoryService.addMedia({ + mediaType: "photo", + method: "getPhoto", + path: result.path || "", + webPath: result.webPath || "", + }); + } + }; + + handlePhotosResult = (photos: GalleryPhoto[]): void => { + this.setState({ + singlePhoto: null, + multiplePhotos: photos, + }); + + photos.forEach((photo) => { + MediaHistoryService.addMedia({ + mediaType: "photo", + method: "chooseFromGallery", + path: photo.path || "", + webPath: photo.webPath, + format: photo.format, + }); + }); + }; + + pickLimitedLibraryPhotos = async (): Promise => { + try { + const res = await Camera.pickLimitedLibraryPhotos(); + this.handlePhotosResult(res.photos); + } catch (e) { + const error = e as any; + const errorMessage = error.code ? `[${error.code}] ${error.message}` : error.message; + alert(`Failed to pick limited library photos with error:\n${errorMessage}`); + } + }; + + getLimitedLibraryPhotos = async (): Promise => { + try { + const res = await Camera.getLimitedLibraryPhotos(); + this.handlePhotosResult(res.photos); + } catch (e) { + const error = e as any; + const errorMessage = error.code ? `[${error.code}] ${error.message}` : error.message; + alert(`Failed to get limited library photos with error:\n${errorMessage}`); + } + }; + + clearMedia = (): void => { + this.setState({ + singlePhoto: null, + multiplePhotos: null, + editedPhoto: null, + }); + }; + + handleEditPhoto = async (filePath: string): Promise => { + try { + const result = await Camera.editURIPhoto({ + uri: filePath, + saveToGallery: false, + includeMetadata: true, + }); + this.setState({ editedPhoto: result }); + + MediaHistoryService.addMedia({ + mediaType: "photo", + method: "editURIPhoto", + path: result.path, + webPath: result.webPath, + format: result.format, + size: result.size, + saved: result.saved, + }); + } catch (e) { + const error = e as any; + const errorMessage = error.code ? `[${error.code}] ${error.message}` : error.message; + alert(`Failed to edit photo with error:\n${errorMessage}`); + } + }; + + render() { + return ( + + + + + + + Gallery + + + + {/* Placeholder for future new methods */} + + + + + {/* Parameter-less methods */} +
+ + (iOS only) pickLimitedLibraryPhotos + + + (iOS only) getLimitedLibraryPhotos + +
+
+
+ + + + + + Old methods + +
+ + + +
+
+
+
+
+ {(this.state.singlePhoto !== null || + (this.state.multiplePhotos !== null && + this.state.multiplePhotos.length > 0)) && ( + + Clear Media + + )} + {this.state.singlePhoto !== null && + this.state.singlePhoto.filePath !== null && ( + + )} + {this.state.multiplePhotos !== null && + this.state.multiplePhotos.length > 0 && ( + + )} + {this.state.editedPhoto !== null && ( + <> +
+

Edited Photo

+
+ + + )} +
+ + + ); + } +} + +export default GalleryPage; diff --git a/example-app/src/pages/Home.tsx b/example-app/src/pages/Home.tsx index cf388d6..4764817 100644 --- a/example-app/src/pages/Home.tsx +++ b/example-app/src/pages/Home.tsx @@ -6,9 +6,11 @@ import { IonPage, IonTitle, IonToolbar, -} from '@ionic/react'; -import ExploreContainer from '../components/ExploreContainer'; -import './Home.css'; + IonCard, + IonCardContent, + IonButton, +} from "@ionic/react"; +import "./Home.css"; const Home: React.FC = () => { return ( @@ -18,16 +20,44 @@ const Home: React.FC = () => { - Blank + Capacitor Camera Example - Blank; TODO - This page will have content in a future PR + Capacitor Camera Example - + + +

+ Demo app showcasing the Capacitor Camera plugin features. Click one of the buttons to test a particular portion of the plugin. +

+
+
+ + + + Permissions + + + Take Picture + + + Gallery + + + Record Video + + + Edit Photo + + + Media History + + +
); diff --git a/example-app/src/pages/MediaHistoryPage.tsx b/example-app/src/pages/MediaHistoryPage.tsx new file mode 100644 index 0000000..66a86e8 --- /dev/null +++ b/example-app/src/pages/MediaHistoryPage.tsx @@ -0,0 +1,192 @@ +import { + IonButtons, + IonContent, + IonHeader, + IonPage, + IonMenuButton, + IonTitle, + IonToolbar, + IonCard, + IonCardContent, + IonList, + IonItem, + IonLabel, + IonBadge, + useIonViewWillEnter, +} from "@ionic/react"; +import React, { useState } from "react"; +import { + MediaHistoryService, + MediaHistoryItem, +} from "../services/MediaHistoryService"; +import { FileViewer } from "@capacitor/file-viewer"; + +const MediaHistoryPage: React.FC = () => { + const [history, setHistory] = useState([]); + + useIonViewWillEnter(() => { + loadHistory(); + }); + + const loadHistory = (): void => { + const history = MediaHistoryService.getAllMedia(); + setHistory(history); + }; + + const openFile = async (item: MediaHistoryItem): Promise => { + try { + await FileViewer.openDocumentFromLocalPath({ path: item.path }); + } catch (e) { + const error = e as any; + const errorMessage = error.code ? `[${error.code}] ${error.message}` : error.message; + alert(`Failed to open file with error:\n${errorMessage}`); + } + }; + + const formatDate = (timestamp: number): string => { + const date = new Date(timestamp); + const now = new Date(); + const isToday = date.toDateString() === now.toDateString(); + + const timeString = date.toLocaleTimeString("en-US", { + hour: "numeric", + minute: "2-digit", + hour12: true, + }); + + if (isToday) { + return `Today, ${timeString}`; + } + + const dateString = date.toLocaleDateString("en-US", { + month: "short", + day: "numeric", + }); + + return `${dateString}, ${timeString}`; + }; + + const formatSize = (bytes?: number): string => { + if (!bytes) { + return "N/A"; + } + + const kb = bytes / 1024; + if (kb < 1024) { + return `${kb.toFixed(1)} KB`; + } + + const mb = kb / 1024; + return `${mb.toFixed(1)} MB`; + }; + + const formatDuration = (seconds?: number): string => { + if (!seconds) { + return "N/A"; + } + + const mins = Math.floor(seconds / 60); + const secs = Math.floor(seconds % 60); + + if (mins > 0) { + return `${mins}m ${secs}s`; + } + + return `${secs}s`; + }; + + return ( + + + + + + + Media History + + + + + +

+ This page displays a chronological list of all media operations + performed using the Camera plugin. History is stored in + localStorage and persists across sessions. +

+

Click a media item to open them.

+
+
+ + {history.length === 0 ? ( + + +

+ No media history yet. Capture or select photos/videos to see + them here. +

+
+
+ ) : ( + + + + {history.map((item) => ( + openFile(item)} + > + +
+ + {item.mediaType === "photo" ? "📷" : "🎥"}{" "} + {item.mediaType} + + {item.method} +
+

+ {formatDate(item.timestamp)} +

+

+ Format: {item.format || "N/A"} | Size:{" "} + {formatSize(item.size)} + {item.mediaType === "video" && + ` | Duration: ${formatDuration(item.duration)}`} + {item.saved !== undefined && + ` | Saved: ${item.saved ? "Yes" : "No"}`} +

+

+ {item.path} +

+
+
+ ))} +
+
+
+ )} + +
+ + + ); +}; + +export default MediaHistoryPage; diff --git a/example-app/src/pages/PermissionsPage.tsx b/example-app/src/pages/PermissionsPage.tsx new file mode 100644 index 0000000..04d99b2 --- /dev/null +++ b/example-app/src/pages/PermissionsPage.tsx @@ -0,0 +1,151 @@ +import { + IonButtons, + IonContent, + IonHeader, + IonPage, + IonMenuButton, + IonTitle, + IonToolbar, + IonCardContent, + IonCard, + IonButton, + IonItem, + IonLabel, + IonBadge, + IonList, +} from "@ionic/react"; +import React from "react"; +import { + Camera, + CameraPluginPermissions, + CameraPermissionState, +} from "@capacitor/camera"; + +interface IPermissionsPageState { + cameraPermission: CameraPermissionState | null; + photosPermission: CameraPermissionState | null; +} + +class PermissionsPage extends React.Component<{}, IPermissionsPageState> { + constructor(props: {}) { + super(props); + this.state = { + cameraPermission: null, + photosPermission: null, + }; + } + + async componentDidMount(): Promise { + await this.loadPermissions(); + } + + loadPermissions = async (): Promise => { + try { + const permissionStates = await Camera.checkPermissions(); + this.setState({ + cameraPermission: permissionStates.camera, + photosPermission: permissionStates.photos, + }); + } catch (e) { + const error = e as any; + const errorMessage = error.code ? `[${error.code}] ${error.message}` : error.message; + alert(`Failed to check permissions with error:\n${errorMessage}`); + } + }; + + requestPermissions = async ( + permissions?: CameraPluginPermissions, + ): Promise => { + try { + const permissionStates = await Camera.requestPermissions(permissions); + this.setState({ + cameraPermission: permissionStates.camera, + photosPermission: permissionStates.photos, + }); + } catch (e) { + const error = e as any; + const errorMessage = error.code ? `[${error.code}] ${error.message}` : error.message; + alert(`Failed to request permissions with error:\n${errorMessage}`); + } + }; + + getPermissionColor = (permission: CameraPermissionState | null): string => { + if (permission === "granted") { + return "success"; + } + if (permission === "denied") { + return "danger"; + } + if (permission === "prompt" || permission === "limited") { + return "warning"; + } + return "medium"; + }; + + render() { + return ( + + + + + + + Permissions + + + + + + + + Camera Permission + + {this.state.cameraPermission ?? "unknown"} + + + + Photos Permission + + {this.state.photosPermission ?? "unknown"} + + + + + + + + + this.requestPermissions({ permissions: ["camera"] }) + } + > + Request Camera Permissions + + + this.requestPermissions({ permissions: ["photos"] }) + } + > + Request Photo Permissions + + this.requestPermissions()} + > + Request All Permissions + + + + + + ); + } +} + +export default PermissionsPage; diff --git a/example-app/src/pages/RecordVideoPage.tsx b/example-app/src/pages/RecordVideoPage.tsx new file mode 100644 index 0000000..032582f --- /dev/null +++ b/example-app/src/pages/RecordVideoPage.tsx @@ -0,0 +1,132 @@ +import { + IonButtons, + IonContent, + IonHeader, + IonPage, + IonMenuButton, + IonTitle, + IonToolbar, + IonCardContent, + IonCard, + IonButton, +} from "@ionic/react"; +import React from "react"; +import { Camera } from "@capacitor/camera"; +import VideoWithMetadata from "../components/camera/VideoWithMetadata"; +import RecordVideoConfigurable from "../components/camera/RecordVideoConfigurable"; +import { MediaHistoryService } from "../services/MediaHistoryService"; + +interface IRecordVideoPageState { + filePath: string | null; + metadata: string | null; +} + +class RecordVideoPage extends React.Component<{}, IRecordVideoPageState> { + constructor(props: {}) { + super(props); + this.state = { + filePath: null, + metadata: null, + }; + } + + handleVideoResult = (result: { + path: string; + webPath: string; + duration?: number; + size: number; + format: string; + saved: boolean; + }): void => { + const metadata = { + duration: result.duration, + size: result.size, + format: result.format, + saved: result.saved, + }; + + this.setState({ + filePath: result.path ?? result.webPath, + metadata: JSON.stringify(metadata, null, 2), + }); + + MediaHistoryService.addMedia({ + mediaType: "video", + method: "recordVideo", + path: result.path, + webPath: result.webPath, + format: result.format, + size: result.size, + duration: result.duration, + saved: result.saved, + }); + }; + + playVideo = async (): Promise => { + if (!this.state.filePath) return; + + try { + await Camera.playVideo({ videoURI: this.state.filePath }); + } catch (e) { + const error = e as any; + const errorMessage = error.code ? `[${error.code}] ${error.message}` : error.message; + alert(`Failed to play video with error:\n${errorMessage}`); + } + }; + + clearVideo = (): void => { + this.setState({ + filePath: null, + metadata: null, + }); + }; + + render() { + return ( + + + + + + + Record Video + + + + + + + + + {this.state.filePath !== null && ( + <> + + + this.playVideo()}> + Play Video + + + + + Clear Video + + + + )} +
+ + + ); + } +} + +export default RecordVideoPage; diff --git a/example-app/src/pages/TakePicturePage.tsx b/example-app/src/pages/TakePicturePage.tsx new file mode 100644 index 0000000..1a79616 --- /dev/null +++ b/example-app/src/pages/TakePicturePage.tsx @@ -0,0 +1,212 @@ +import { + IonButton, + IonButtons, + IonContent, + IonHeader, + IonPage, + IonMenuButton, + IonTitle, + IonToolbar, + IonCardContent, + IonCard, + IonAccordion, + IonAccordionGroup, + IonItem, + IonLabel, +} from "@ionic/react"; +import React from "react"; +import { Camera, CameraSource } from "@capacitor/camera"; +import PhotoWithMetadata from "../components/camera/PhotoWithMetadata"; +import TakePictureConfigurable from "../components/camera/TakePictureConfigurable"; +import { GetPhotoConfigurable } from "../components/camera/old-methods"; +import { MediaHistoryService } from "../services/MediaHistoryService"; + +interface MediaResult { + path: string; + webPath: string; + duration?: number; + size: number; + format: string; + saved: boolean; +} + +interface ITakePicturePageState { + filePath: string | null; + metadata: string | null; + editedPhoto: MediaResult | null; +} + +class TakePicturePage extends React.Component<{}, ITakePicturePageState> { + constructor(props: {}) { + super(props); + this.state = { + filePath: null, + metadata: null, + editedPhoto: null, + }; + } + + handleTakePhotoResult = (result: { + path: string; + webPath: string; + duration?: number; + size: number; + format: string; + saved: boolean; + }): void => { + const metadata = { + size: result.size, + format: result.format, + saved: result.saved, + }; + + this.setState({ + filePath: result.path ?? result.webPath, + metadata: JSON.stringify(metadata, null, 2), + }); + + MediaHistoryService.addMedia({ + mediaType: "photo", + method: "takePhoto", + path: result.path, + webPath: result.webPath, + format: result.format, + size: result.size, + saved: result.saved, + }); + }; + + handlePhotoResult = (result: { + path?: string; + webPath?: string; + exif?: any; + }): void => { + this.setState({ + filePath: result.path ?? result.webPath ?? null, + metadata: JSON.stringify(result.exif, null, 2), + }); + + if (result.path || result.webPath) { + MediaHistoryService.addMedia({ + mediaType: "photo", + method: "getPhoto", + path: result.path || "", + webPath: result.webPath || "", + }); + } + }; + + clearPhoto = (): void => { + this.setState({ + filePath: null, + metadata: null, + editedPhoto: null, + }); + }; + + handleEditPhoto = async (filePath: string): Promise => { + try { + const result = await Camera.editURIPhoto({ + uri: filePath, + saveToGallery: false, + includeMetadata: true, + }); + this.setState({ editedPhoto: result }); + + MediaHistoryService.addMedia({ + mediaType: "photo", + method: "editURIPhoto", + path: result.path, + webPath: result.webPath, + format: result.format, + size: result.size, + saved: result.saved, + }); + } catch (e) { + const error = e as any; + const errorMessage = error.code ? `[${error.code}] ${error.message}` : error.message; + alert(`Failed to edit photo with error:\n${errorMessage}`); + } + }; + + render() { + return ( + + + + + + + Take Picture + + + + + + + + + + + + + + Old methods + +
+ +
+
+
+
+
+ {this.state.filePath !== null && ( + <> + + Clear Photo + + + + )} + {this.state.editedPhoto !== null && ( + <> +
+

Edited Photo

+
+ + + )} +
+ + + ); + } +} + +export default TakePicturePage; diff --git a/example-app/src/routes.tsx b/example-app/src/routes.tsx index 8ef70a4..149caa9 100644 --- a/example-app/src/routes.tsx +++ b/example-app/src/routes.tsx @@ -1,12 +1,17 @@ import React from "react"; -import Camera from "./pages/Camera"; import Home from "./pages/Home"; +import PermissionsPage from "./pages/PermissionsPage"; +import TakePicturePage from "./pages/TakePicturePage"; +import GalleryPage from "./pages/GalleryPage"; +import RecordVideoPage from "./pages/RecordVideoPage"; +import EditPhotoPage from "./pages/EditPhotoPage"; +import MediaHistoryPage from "./pages/MediaHistoryPage"; export interface Page { readonly url: string; readonly title: string; - readonly icon: JSX.Element; - readonly component: typeof React.Component | React.FC; + readonly icon: React.ReactElement; + readonly component: React.ComponentType; } export const routes: Page[] = [ @@ -20,14 +25,64 @@ export const routes: Page[] = [ ), component: Home, }, + { + url: "/permissions", + title: "Permissions", + icon: ( + + 🔐 + + ), + component: PermissionsPage, + }, { url: "/camera", - title: "Camera", + title: "Take Picture", icon: ( 📷 ), - component: Camera, + component: TakePicturePage, + }, + { + url: "/gallery", + title: "Gallery", + icon: ( + + 🖼️ + + ), + component: GalleryPage, + }, + { + url: "/video", + title: "Record Video", + icon: ( + + 🎥 + + ), + component: RecordVideoPage, + }, + { + url: "/edit", + title: "Edit Photo", + icon: ( + + ✏️ + + ), + component: EditPhotoPage, + }, + { + url: "/history", + title: "Media History", + icon: ( + + 📋 + + ), + component: MediaHistoryPage, }, ]; diff --git a/example-app/src/services/MediaHistoryService.ts b/example-app/src/services/MediaHistoryService.ts new file mode 100644 index 0000000..24cfc79 --- /dev/null +++ b/example-app/src/services/MediaHistoryService.ts @@ -0,0 +1,66 @@ +export interface MediaHistoryItem { + id: string; + timestamp: number; + mediaType: "photo" | "video"; + method: string; + path: string; + webPath: string; + format?: string; + size?: number; + duration?: number; + saved?: boolean; +} + +class MediaHistoryServiceClass { + private readonly STORAGE_KEY = "capacitor_camera_media_history"; + private readonly MAX_ITEMS = 100; + + addMedia(item: Omit): void { + try { + const timestamp = Date.now(); + const id = `${timestamp}-${Math.random().toString(36).substring(2, 9)}`; + + const newItem: MediaHistoryItem = { + ...item, + id, + timestamp, + }; + + const history = this.getAllMedia(); + history.unshift(newItem); + + const trimmedHistory = history.slice(0, this.MAX_ITEMS); + + localStorage.setItem(this.STORAGE_KEY, JSON.stringify(trimmedHistory)); + } catch (error) { + console.error("Failed to add media to history:", error); + } + } + + getAllMedia(): MediaHistoryItem[] { + try { + const data = localStorage.getItem(this.STORAGE_KEY); + if (!data) { + return []; + } + return JSON.parse(data); + } catch (error) { + console.error("Failed to retrieve media history:", error); + return []; + } + } + + clearHistory(): void { + try { + localStorage.removeItem(this.STORAGE_KEY); + } catch (error) { + console.error("Failed to clear media history:", error); + } + } + + getCount(): number { + return this.getAllMedia().length; + } +} + +export const MediaHistoryService = new MediaHistoryServiceClass(); diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..55fa52b --- /dev/null +++ b/package-lock.json @@ -0,0 +1,4922 @@ +{ + "name": "@capacitor/camera", + "version": "8.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@capacitor/camera", + "version": "8.0.1", + "license": "MIT", + "devDependencies": { + "@capacitor/android": "^8.0.0", + "@capacitor/core": "^8.0.0", + "@capacitor/docgen": "0.3.0", + "@capacitor/ios": "^8.0.0", + "@ionic/eslint-config": "^0.4.0", + "@ionic/prettier-config": "^4.0.0", + "@ionic/swiftlint-config": "^2.0.0", + "@types/node": "^25.3.3", + "eslint": "^8.57.1", + "prettier": "^3.6.2", + "prettier-plugin-java": "^2.7.7", + "rimraf": "^6.1.0", + "rollup": "^4.53.2", + "swiftlint": "^2.0.0", + "typescript": "^5.9.3" + }, + "peerDependencies": { + "@capacitor/core": ">=8.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@capacitor/android": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@capacitor/android/-/android-8.1.0.tgz", + "integrity": "sha512-z0acTPxj5DCy/U2FU7w+GA93oC+wdyKnsOcRg5rutDmSYa8Do1tzYqApKgf+hnuTNPbtrCTHp0Zy1cLiK/4MEw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@capacitor/core": "^8.1.0" + } + }, + "node_modules/@capacitor/core": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-8.1.0.tgz", + "integrity": "sha512-UfMBMWc1v7J+14AhH03QmeNwV3HZx3qnOWhpwnHfzALEwAwlV/itQOQqcasMQYhOHWL0tiymc5ByaLTn7KKQxw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@capacitor/docgen": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@capacitor/docgen/-/docgen-0.3.0.tgz", + "integrity": "sha512-WPggobo5Ql70F+2xOIUwNSApJXaL9F/9+Al6B+sNuSAmcg484OAksyUPKgiynF4BVlxeY5a0sDkgdVkmmA3ElQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "^14.18.0", + "colorette": "^2.0.20", + "github-slugger": "^1.5.0", + "minimist": "^1.2.8", + "typescript": "~4.2.4" + }, + "bin": { + "docgen": "bin/docgen" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@capacitor/docgen/node_modules/@types/node": { + "version": "14.18.63", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.63.tgz", + "integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@capacitor/docgen/node_modules/typescript": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", + "integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/@capacitor/ios": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@capacitor/ios/-/ios-8.1.0.tgz", + "integrity": "sha512-wPaQ8ayL0UY+SxydZbrmfzPs8TryZVEB6hrL/XBnXxQtb6rpEmIy/3GIltPwM+/T4m/IuaSDZOToWK65ruC00g==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@capacitor/core": "^8.1.0" + } + }, + "node_modules/@chevrotain/cst-dts-gen": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.0.3.tgz", + "integrity": "sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/gast": "11.0.3", + "@chevrotain/types": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/@chevrotain/gast": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-11.0.3.tgz", + "integrity": "sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/types": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/@chevrotain/regexp-to-ast": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-11.0.3.tgz", + "integrity": "sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@chevrotain/types": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.0.3.tgz", + "integrity": "sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@chevrotain/utils": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-11.0.3.tgz", + "integrity": "sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@ionic/eslint-config": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@ionic/eslint-config/-/eslint-config-0.4.0.tgz", + "integrity": "sha512-L8OXY29D3iGqNtteFj0iz3eoZIVgokBiVjCO8WMssNZa4GTHjYsase0rC9ASXGefMnLJu6rbNl3Gbx7NNxJRZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "^5.58.0", + "@typescript-eslint/parser": "^5.58.0", + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-import": "^2.27.0" + }, + "peerDependencies": { + "eslint": ">=7" + } + }, + "node_modules/@ionic/prettier-config": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@ionic/prettier-config/-/prettier-config-4.0.0.tgz", + "integrity": "sha512-0DqL6CggVdgeJAWOLPUT73rF1VD5p0tVlCpC5GXz5vTIUBxNwsJ5085Q7wXjKiE5Odx3aOHGTcuRWCawFsLFag==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "prettier": "^2.4.0 || ^3.0.0" + } + }, + "node_modules/@ionic/swiftlint-config": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@ionic/swiftlint-config/-/swiftlint-config-2.0.0.tgz", + "integrity": "sha512-TXy76ALSKhUZzBziHz7aoEtSQwHofBIDRNzM9x4sndtC7fefbZsBw3UgGwXFTOc7hoj72EAGyqZNUhj9LlhaNQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@ionic/utils-array": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@ionic/utils-array/-/utils-array-2.1.6.tgz", + "integrity": "sha512-0JZ1Zkp3wURnv8oq6Qt7fMPo5MpjbLoUoa9Bu2Q4PJuSDWM8H8gwF3dQO7VTeUj3/0o1IB1wGkFWZZYgUXZMUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-fs": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@ionic/utils-fs/-/utils-fs-3.1.7.tgz", + "integrity": "sha512-2EknRvMVfhnyhL1VhFkSLa5gOcycK91VnjfrTB0kbqkTFCOXyXgVLI5whzq7SLrgD9t1aqos3lMMQyVzaQ5gVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/fs-extra": "^8.0.0", + "debug": "^4.0.0", + "fs-extra": "^9.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-object": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@ionic/utils-object/-/utils-object-2.1.6.tgz", + "integrity": "sha512-vCl7sl6JjBHFw99CuAqHljYJpcE88YaH2ZW4ELiC/Zwxl5tiwn4kbdP/gxi2OT3MQb1vOtgAmSNRtusvgxI8ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-process": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@ionic/utils-process/-/utils-process-2.1.12.tgz", + "integrity": "sha512-Jqkgyq7zBs/v/J3YvKtQQiIcxfJyplPgECMWgdO0E1fKrrH8EF0QGHNJ9mJCn6PYe2UtHNS8JJf5G21e09DfYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ionic/utils-object": "2.1.6", + "@ionic/utils-terminal": "2.3.5", + "debug": "^4.0.0", + "signal-exit": "^3.0.3", + "tree-kill": "^1.2.2", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@ionic/utils-stream/-/utils-stream-3.1.7.tgz", + "integrity": "sha512-eSELBE7NWNFIHTbTC2jiMvh1ABKGIpGdUIvARsNPMNQhxJB3wpwdiVnoBoTYp+5a6UUIww4Kpg7v6S7iTctH1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-subprocess": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@ionic/utils-subprocess/-/utils-subprocess-3.0.1.tgz", + "integrity": "sha512-cT4te3AQQPeIM9WCwIg8ohroJ8TjsYaMb2G4ZEgv9YzeDqHZ4JpeIKqG2SoaA3GmVQ3sOfhPM6Ox9sxphV/d1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ionic/utils-array": "2.1.6", + "@ionic/utils-fs": "3.1.7", + "@ionic/utils-process": "2.1.12", + "@ionic/utils-stream": "3.1.7", + "@ionic/utils-terminal": "2.3.5", + "cross-spawn": "^7.0.3", + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-terminal": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@ionic/utils-terminal/-/utils-terminal-2.3.5.tgz", + "integrity": "sha512-3cKScz9Jx2/Pr9ijj1OzGlBDfcmx7OMVBt4+P1uRR0SSW4cm1/y3Mo4OY3lfkuaYifMNBW8Wz6lQHbs1bihr7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/slice-ansi": "^4.0.0", + "debug": "^4.0.0", + "signal-exit": "^3.0.3", + "slice-ansi": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "tslib": "^2.0.1", + "untildify": "^4.0.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", + "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", + "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", + "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", + "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", + "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", + "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", + "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", + "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", + "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", + "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", + "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", + "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", + "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", + "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", + "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", + "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", + "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", + "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", + "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", + "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", + "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", + "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", + "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", + "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", + "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/fs-extra": { + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.5.tgz", + "integrity": "sha512-0dzKcwO+S8s2kuF5Z9oUWatQJj5Uq/iqphEtE3GQJVRRYm/tD1LglU2UnXi2A8jLq5umkGouOXOR9y0n613ZwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "25.3.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.3.3.tgz", + "integrity": "sha512-DpzbrH7wIcBaJibpKo9nnSQL0MTRdnWttGyE5haGwK86xgMOkFLp7vEyfQPGLOJh5wNYiJ3V9PmUMDhV9u8kkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.18.0" + } + }, + "node_modules/@types/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-+OpjSaq85gvlZAYINyzKpLeiFkSC4EsC6IIiT6v6TLSU5k5U83fHGj9Lel8oKEXM0HqgrMVCjXPDPVICtxF7EQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", + "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", + "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", + "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC" + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chevrotain": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.0.3.tgz", + "integrity": "sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@chevrotain/cst-dts-gen": "11.0.3", + "@chevrotain/gast": "11.0.3", + "@chevrotain/regexp-to-ast": "11.0.3", + "@chevrotain/types": "11.0.3", + "@chevrotain/utils": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/chevrotain-allstar": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/chevrotain-allstar/-/chevrotain-allstar-0.3.1.tgz", + "integrity": "sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash-es": "^4.17.21" + }, + "peerDependencies": { + "chevrotain": "^11.0.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cosmiconfig": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.1.tgz", + "integrity": "sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.24.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.1.tgz", + "integrity": "sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "8.10.2", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.2.tgz", + "integrity": "sha512-/IGJ6+Dka158JnP5n5YFMOszjDWrXggGz1LaK/guZq9vZTmniaKlHcsscvkAhn9y4U+BU3JuUdYvtAMcv30y4A==", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.9", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flat-cache/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/flat-cache/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/flatted": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.4.tgz", + "integrity": "sha512-3+mMldrTAPdta5kjX2G2J7iX4zxtnwpdA8Tr2ZSjkyPSanvbZAcy6flmtnXbEybHrDcU9641lxrMfFuUxVz9vA==", + "dev": true, + "license": "ISC" + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/github-slugger": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.5.0.tgz", + "integrity": "sha512-wIh+gKBI9Nshz2o46B0B3f5k/W+WI9ZAv6y5Dn5WJ5SK1t0TnDimB4WE5rmTD05ZAIn8HALCZVmCsvj0w0v0lw==", + "dev": true, + "license": "ISC" + }, + "node_modules/glob": { + "version": "13.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "minimatch": "^10.2.2", + "minipass": "^7.1.3", + "path-scurry": "^2.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", + "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/java-parser": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/java-parser/-/java-parser-3.0.1.tgz", + "integrity": "sha512-sDIR7u9b7O2JViNUxiZRhnRz7URII/eE7g2B+BmGxDeS6Ex3OYAcCyz5oh0H4LQ+hL/BS8OJTz8apMy9xtGmrQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "chevrotain": "11.0.3", + "chevrotain-allstar": "0.3.1", + "lodash": "4.17.21" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "11.2.6", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", + "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true, + "license": "MIT" + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", + "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-plugin-java": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/prettier-plugin-java/-/prettier-plugin-java-2.8.1.tgz", + "integrity": "sha512-tkteH5OSCEb0E7wKnhhUSitr1pGUCUt9M//CwerSNhoalL/qv0jXTeSVBPZ36KC+kZl3nbq4dxh144NuGchACg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "java-parser": "3.0.1" + }, + "peerDependencies": { + "prettier": "^3.0.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.3.tgz", + "integrity": "sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "glob": "^13.0.3", + "package-json-from-dist": "^1.0.1" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", + "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.59.0", + "@rollup/rollup-android-arm64": "4.59.0", + "@rollup/rollup-darwin-arm64": "4.59.0", + "@rollup/rollup-darwin-x64": "4.59.0", + "@rollup/rollup-freebsd-arm64": "4.59.0", + "@rollup/rollup-freebsd-x64": "4.59.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", + "@rollup/rollup-linux-arm-musleabihf": "4.59.0", + "@rollup/rollup-linux-arm64-gnu": "4.59.0", + "@rollup/rollup-linux-arm64-musl": "4.59.0", + "@rollup/rollup-linux-loong64-gnu": "4.59.0", + "@rollup/rollup-linux-loong64-musl": "4.59.0", + "@rollup/rollup-linux-ppc64-gnu": "4.59.0", + "@rollup/rollup-linux-ppc64-musl": "4.59.0", + "@rollup/rollup-linux-riscv64-gnu": "4.59.0", + "@rollup/rollup-linux-riscv64-musl": "4.59.0", + "@rollup/rollup-linux-s390x-gnu": "4.59.0", + "@rollup/rollup-linux-x64-gnu": "4.59.0", + "@rollup/rollup-linux-x64-musl": "4.59.0", + "@rollup/rollup-openbsd-x64": "4.59.0", + "@rollup/rollup-openharmony-arm64": "4.59.0", + "@rollup/rollup-win32-arm64-msvc": "4.59.0", + "@rollup/rollup-win32-ia32-msvc": "4.59.0", + "@rollup/rollup-win32-x64-gnu": "4.59.0", + "@rollup/rollup-win32-x64-msvc": "4.59.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/swiftlint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/swiftlint/-/swiftlint-2.0.0.tgz", + "integrity": "sha512-MMVuyZ4/6WcIJlk0z6GM0pZjRuwnyUJqRPbJBFW3oACN/qjAvRbolCWEu+zE2MycF/cEgqfUpI+oLECNfjfOJA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@ionic/utils-fs": "^3.1.7", + "@ionic/utils-subprocess": "^3.0.1", + "cosmiconfig": "^9.0.0" + }, + "bin": { + "node-swiftlint": "bin.js" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "license": "0BSD" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undici-types": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", + "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.20", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz", + "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/src/definitions.ts b/src/definitions.ts index 841dd8e..525f827 100644 --- a/src/definitions.ts +++ b/src/definitions.ts @@ -22,14 +22,6 @@ export interface CameraPlugin { */ getPhoto(options: ImageOptions): Promise; - /** - * Prompt the user to pick a photo from an album, or take a new photo - * with the camera. - * - * @since 1.0.0 - */ - takePhoto(options: ImageOptions): Promise; - /** * Allows the user to pick multiple pictures from the photo gallery. * @@ -66,9 +58,37 @@ export interface CameraPlugin { */ requestPermissions(permissions?: CameraPluginPermissions): Promise; + /** + * Prompt the user to take a photo with the camera. + * + * @since 2.0.0 + */ + takePhoto(options: ImageOptions): Promise; + recordVideo(options: RecordVideoOptions): Promise; - playVideo(options: { videoURI: string }): Promise; + playVideo(options: PlayVideoOptions): Promise; + + /** + * Allows the user to pick multiple pictures from the photo gallery. + * + * @since 1.2.0 + */ + chooseFromGallery(options: GalleryOptions): Promise; + + /** + * Returns a string (base64) representing the photo that was edited + * + * @since 2.0.0 + */ + editPhoto(options: EditPhotoOptions): Promise; + + /** + * Returns a MediaResult object with info about the photo that was edited + * + * @since 2.0.0 + */ + editURIPhoto(options: EditURIPhotoOptions): Promise; } export interface RecordVideoOptions { @@ -76,9 +96,47 @@ export interface RecordVideoOptions { includeMetadata?: boolean; } +export interface PlayVideoOptions { + videoURI: string; +} + +export interface GalleryOptions { + mediaType: MediaType; + allowMultipleSelection?: boolean; + limit?: number; + includeMetadata?: boolean; + allowEdit?: boolean; + editInApp?: boolean; + presentationStyle?: 'fullscreen' | 'popover'; + quality?: number; + width?: number; + height?: number; + correctOrientation?: boolean; +} + +export interface EditURIPhotoOptions { + uri?: string; + saveToGallery?: boolean; + includeMetadata?: boolean; +} + +export interface EditPhotoOptions { + base64?: string; +} + +export interface EditPhotoResult { + format: string; + base64String: string; +} + +export interface MediaResults { + photos: MediaResult[]; +} + export interface MediaResult { path: string; webPath: string; + exif?: any; duration?: number; size: number; format: string; @@ -375,6 +433,12 @@ export enum CameraResultType { DataUrl = 'dataUrl', } +export enum MediaType { + picture = 0, + video = 1, + all = 2, +} + /** * @deprecated Use `Photo`. * @since 1.0.0 diff --git a/src/web.ts b/src/web.ts index e14daa0..c387eb4 100644 --- a/src/web.ts +++ b/src/web.ts @@ -9,50 +9,41 @@ import type { PermissionStatus, Photo, RecordVideoOptions, + EditPhotoOptions, + PlayVideoOptions, + EditURIPhotoOptions, + EditPhotoResult, MediaResult, + MediaResults, + GalleryOptions, } from './definitions'; export class CameraWeb extends WebPlugin implements CameraPlugin { + async takePhoto(_options: ImageOptions): Promise { + throw this.unimplemented('takePhoto is not implemented on Web.'); + } + async recordVideo(_options: RecordVideoOptions): Promise { - throw this.unimplemented('recordVideo is not implemented on web.'); + throw this.unimplemented('recordVideo is not implemented on Web.'); } - async playVideo(_options: { videoURI: string }): Promise { - throw this.unimplemented('playVideo is not implemented on web.'); + async playVideo(_options: PlayVideoOptions): Promise { + throw this.unimplemented('playVideo is not implemented on Web.'); } - async getPhoto(options: ImageOptions): Promise { - // eslint-disable-next-line no-async-promise-executor - return new Promise(async (resolve, reject) => { - if (options.webUseInput || options.source === CameraSource.Photos) { - this.fileInputExperience(options, resolve, reject); - } else if (options.source === CameraSource.Prompt) { - let actionSheet: any = document.querySelector('pwa-action-sheet'); - if (!actionSheet) { - actionSheet = document.createElement('pwa-action-sheet'); - document.body.appendChild(actionSheet); - } - actionSheet.header = options.promptLabelHeader || 'Photo'; - actionSheet.cancelable = false; - actionSheet.options = [ - { title: options.promptLabelPhoto || 'From Photos' }, - { title: options.promptLabelPicture || 'Take Picture' }, - ]; - actionSheet.addEventListener('onSelection', async (e: any) => { - const selection = e.detail; - if (selection === 0) { - this.fileInputExperience(options, resolve, reject); - } else { - this.cameraExperience(options, resolve, reject); - } - }); - } else { - this.cameraExperience(options, resolve, reject); - } - }); + async chooseFromGallery(_options: GalleryOptions): Promise { + throw this.unimplemented('chooseFromGallery is not implemented on web.'); } - async takePhoto(options: ImageOptions): Promise { + async editPhoto(_options: EditPhotoOptions): Promise { + throw this.unimplemented('editPhoto is not implemented on Web.'); + } + + async editURIPhoto(_options: EditURIPhotoOptions): Promise { + throw this.unimplemented('editURIPhoto is not implemented on Web.'); + } + + async getPhoto(options: ImageOptions): Promise { // eslint-disable-next-line no-async-promise-executor return new Promise(async (resolve, reject) => { if (options.webUseInput || options.source === CameraSource.Photos) { @@ -64,7 +55,7 @@ export class CameraWeb extends WebPlugin implements CameraPlugin { document.body.appendChild(actionSheet); } actionSheet.header = options.promptLabelHeader || 'Photo'; - actionSheet.cancelable = true; + actionSheet.cancelable = false; actionSheet.options = [ { title: options.promptLabelPhoto || 'From Photos' }, { title: options.promptLabelPicture || 'Take Picture' }, @@ -77,9 +68,6 @@ export class CameraWeb extends WebPlugin implements CameraPlugin { this.cameraExperience(options, resolve, reject); } }); - actionSheet.addEventListener('onCanceled', async () => { - reject(new CapacitorException('User cancelled photos app')); - }); } else { this.cameraExperience(options, resolve, reject); }