From 469d5838fb3f9387e21a9f21a6f262e83a960484 Mon Sep 17 00:00:00 2001 From: EQuimper Date: Sat, 14 Mar 2026 08:03:53 -0400 Subject: [PATCH 1/6] feat: add per-property transition support to EaseView --- README.md | 57 + android/src/main/java/com/ease/EaseView.kt | 256 +- .../src/main/java/com/ease/EaseViewManager.kt | 64 + example/pnpm-lock.yaml | 5986 +++++++++++++++++ example/src/demos/PerPropertyDemo.tsx | 50 + example/src/demos/index.ts | 2 + ios/EaseView.mm | 287 +- src/EaseView.tsx | 221 +- src/EaseViewNativeComponent.ts | 11 + src/__tests__/EaseView.test.tsx | 142 + src/index.tsx | 2 + src/types.ts | 16 +- 12 files changed, 6945 insertions(+), 149 deletions(-) create mode 100644 example/pnpm-lock.yaml create mode 100644 example/src/demos/PerPropertyDemo.tsx diff --git a/README.md b/README.md index f80a357..424d56c 100644 --- a/README.md +++ b/README.md @@ -165,6 +165,42 @@ Use `{ type: 'none' }` to apply values immediately without animation. Useful for `onTransitionEnd` fires immediately with `{ finished: true }`. +### Per-Property Transitions + +Pass a map instead of a single config to use different transition types per property. This lets you mix timing and spring animations, or use different durations for different properties. + +```tsx + +``` + +Use `default` as a fallback for properties not explicitly listed: + +```tsx + +``` + +The `scale` key applies to both `scaleX` and `scaleY`. A specific `scaleX` or `scaleY` key takes priority over `scale`. + +When no `default` key is provided, library defaults apply by category: +- **Transforms** (translateX/Y, scaleX/Y, rotate, rotateX/Y): spring with damping=15, stiffness=120 +- **Other** (opacity, borderRadius, backgroundColor): timing 300ms easeInOut + +> **iOS note:** iOS composes all transform sub-properties into a single `CATransform3D` animation. If your map specifies conflicting configs for different transform properties (e.g. spring for `translateX` and timing for `scaleX`), the config from the lowest-index changed property is used. +> +> **Android note:** Android animates `backgroundColor` with `ValueAnimator` (timing only). If a per-property map specifies `type: 'spring'` for `backgroundColor`, it silently falls back to timing 300ms. + ### Border Radius `borderRadius` can be animated just like other properties. It uses hardware-accelerated platform APIs — `ViewOutlineProvider` + `clipToOutline` on Android and `layer.cornerRadius` + `layer.masksToBounds` on iOS. Unlike RN's style-based `borderRadius` (which uses a Canvas drawable on Android), this clips children properly and is GPU-accelerated. @@ -400,6 +436,27 @@ Properties not specified in `animate` default to their identity values. Applies values instantly with no animation. `onTransitionEnd` fires immediately with `{ finished: true }`. +### `TransitionMap` + +```tsx +{ + default?: SingleTransition; // fallback for unlisted properties + opacity?: SingleTransition; + translateX?: SingleTransition; + translateY?: SingleTransition; + scale?: SingleTransition; // shorthand for scaleX + scaleY + scaleX?: SingleTransition; + scaleY?: SingleTransition; + rotate?: SingleTransition; + rotateX?: SingleTransition; + rotateY?: SingleTransition; + borderRadius?: SingleTransition; + backgroundColor?: SingleTransition; +} +``` + +`Transition` is `SingleTransition | TransitionMap`. The `transition` prop accepts either form. + ## Hardware Layers (Android) Setting `useHardwareLayer` rasterizes the view into a GPU texture for the duration of the animation. This means animated property changes (opacity, scale, rotation) are composited on the RenderThread without redrawing the view hierarchy — useful for complex views with many children. diff --git a/android/src/main/java/com/ease/EaseView.kt b/android/src/main/java/com/ease/EaseView.kt index aebb135..3896441 100644 --- a/android/src/main/java/com/ease/EaseView.kt +++ b/android/src/main/java/com/ease/EaseView.kt @@ -44,6 +44,90 @@ class EaseView(context: Context) : ReactViewGroup(context) { var transitionLoop: String = "none" var transitionDelay: Long = 0L + // --- Per-property transition arrays (set by ViewManager) --- + var perPropertyTransitionTypes: Array? = null + var perPropertyTransitionDurations: IntArray? = null + var perPropertyTransitionDampings: FloatArray? = null + var perPropertyTransitionStiffnesses: FloatArray? = null + var perPropertyTransitionMasses: FloatArray? = null + var perPropertyTransitionLoops: Array? = null + var perPropertyTransitionEasingBeziers: FloatArray? = null + + data class TransitionConfig( + val type: String, + val duration: Int, + val easingBezier: FloatArray, + val damping: Float, + val stiffness: Float, + val mass: Float, + val loop: String + ) + + fun getTransitionConfigForProperty(index: Int): TransitionConfig { + val types = perPropertyTransitionTypes + if (types != null && index < types.size) { + val durations = perPropertyTransitionDurations + val dampings = perPropertyTransitionDampings + val stiffnesses = perPropertyTransitionStiffnesses + val masses = perPropertyTransitionMasses + val loops = perPropertyTransitionLoops + val beziers = perPropertyTransitionEasingBeziers + + val bIdx = index * 4 + val bezier = if (beziers != null && bIdx + 3 < beziers.size) { + floatArrayOf(beziers[bIdx], beziers[bIdx + 1], beziers[bIdx + 2], beziers[bIdx + 3]) + } else { + floatArrayOf(0.42f, 0f, 0.58f, 1.0f) + } + + return TransitionConfig( + type = types[index], + duration = if (durations != null && index < durations.size) durations[index] else 300, + easingBezier = bezier, + damping = if (dampings != null && index < dampings.size) dampings[index] else 15.0f, + stiffness = if (stiffnesses != null && index < stiffnesses.size) stiffnesses[index] else 120.0f, + mass = if (masses != null && index < masses.size) masses[index] else 1.0f, + loop = if (loops != null && index < loops.size) loops[index] else "none" + ) + } + // Fallback to scalar props + return TransitionConfig( + type = transitionType, + duration = transitionDuration, + easingBezier = transitionEasingBezier, + damping = transitionDamping, + stiffness = transitionStiffness, + mass = transitionMass, + loop = transitionLoop + ) + } + + // Property indices matching JS constants + companion object { + // Bitmask flags — must match JS constants + const val MASK_OPACITY = 1 shl 0 + const val MASK_TRANSLATE_X = 1 shl 1 + const val MASK_TRANSLATE_Y = 1 shl 2 + const val MASK_SCALE_X = 1 shl 3 + const val MASK_SCALE_Y = 1 shl 4 + const val MASK_ROTATE = 1 shl 5 + const val MASK_ROTATE_X = 1 shl 6 + const val MASK_ROTATE_Y = 1 shl 7 + const val MASK_BORDER_RADIUS = 1 shl 8 + const val MASK_BACKGROUND_COLOR = 1 shl 9 + + const val PROP_INDEX_OPACITY = 0 + const val PROP_INDEX_TRANSLATE_X = 1 + const val PROP_INDEX_TRANSLATE_Y = 2 + const val PROP_INDEX_SCALE_X = 3 + const val PROP_INDEX_SCALE_Y = 4 + const val PROP_INDEX_ROTATE = 5 + const val PROP_INDEX_ROTATE_X = 6 + const val PROP_INDEX_ROTATE_Y = 7 + const val PROP_INDEX_BORDER_RADIUS = 8 + const val PROP_INDEX_BACKGROUND_COLOR = 9 + } + // --- Transform origin (0–1 fractions) --- var transformOriginX: Float = 0.5f set(value) { @@ -118,20 +202,7 @@ class EaseView(context: Context) : ReactViewGroup(context) { // --- Animated properties bitmask (set by ViewManager) --- var animatedProperties: Int = 0 - // --- Easing interpolators (lazy singletons shared across all instances) --- - companion object { - // Bitmask flags — must match JS constants - const val MASK_OPACITY = 1 shl 0 - const val MASK_TRANSLATE_X = 1 shl 1 - const val MASK_TRANSLATE_Y = 1 shl 2 - const val MASK_SCALE_X = 1 shl 3 - const val MASK_SCALE_Y = 1 shl 4 - const val MASK_ROTATE = 1 shl 5 - const val MASK_ROTATE_X = 1 shl 6 - const val MASK_ROTATE_Y = 1 shl 7 - const val MASK_BORDER_RADIUS = 1 shl 8 - const val MASK_BACKGROUND_COLOR = 1 shl 9 - } + private fun hasPerPropertyArrays(): Boolean = perPropertyTransitionTypes != null init { // Set camera distance for 3D perspective rotations (rotateX/rotateY) @@ -236,34 +307,34 @@ class EaseView(context: Context) : ReactViewGroup(context) { // Animate properties that differ from initial to target if (mask and MASK_OPACITY != 0 && initialAnimateOpacity != opacity) { - animateProperty("alpha", DynamicAnimation.ALPHA, initialAnimateOpacity, opacity, loop = true) + animateProperty("alpha", DynamicAnimation.ALPHA, initialAnimateOpacity, opacity, getTransitionConfigForProperty(PROP_INDEX_OPACITY), loop = true) } if (mask and MASK_TRANSLATE_X != 0 && initialAnimateTranslateX != translateX) { - animateProperty("translationX", DynamicAnimation.TRANSLATION_X, initialAnimateTranslateX, translateX, loop = true) + animateProperty("translationX", DynamicAnimation.TRANSLATION_X, initialAnimateTranslateX, translateX, getTransitionConfigForProperty(PROP_INDEX_TRANSLATE_X), loop = true) } if (mask and MASK_TRANSLATE_Y != 0 && initialAnimateTranslateY != translateY) { - animateProperty("translationY", DynamicAnimation.TRANSLATION_Y, initialAnimateTranslateY, translateY, loop = true) + animateProperty("translationY", DynamicAnimation.TRANSLATION_Y, initialAnimateTranslateY, translateY, getTransitionConfigForProperty(PROP_INDEX_TRANSLATE_Y), loop = true) } if (mask and MASK_SCALE_X != 0 && initialAnimateScaleX != scaleX) { - animateProperty("scaleX", DynamicAnimation.SCALE_X, initialAnimateScaleX, scaleX, loop = true) + animateProperty("scaleX", DynamicAnimation.SCALE_X, initialAnimateScaleX, scaleX, getTransitionConfigForProperty(PROP_INDEX_SCALE_X), loop = true) } if (mask and MASK_SCALE_Y != 0 && initialAnimateScaleY != scaleY) { - animateProperty("scaleY", DynamicAnimation.SCALE_Y, initialAnimateScaleY, scaleY, loop = true) + animateProperty("scaleY", DynamicAnimation.SCALE_Y, initialAnimateScaleY, scaleY, getTransitionConfigForProperty(PROP_INDEX_SCALE_Y), loop = true) } if (mask and MASK_ROTATE != 0 && initialAnimateRotate != rotate) { - animateProperty("rotation", DynamicAnimation.ROTATION, initialAnimateRotate, rotate, loop = true) + animateProperty("rotation", DynamicAnimation.ROTATION, initialAnimateRotate, rotate, getTransitionConfigForProperty(PROP_INDEX_ROTATE), loop = true) } if (mask and MASK_ROTATE_X != 0 && initialAnimateRotateX != rotateX) { - animateProperty("rotationX", DynamicAnimation.ROTATION_X, initialAnimateRotateX, rotateX, loop = true) + animateProperty("rotationX", DynamicAnimation.ROTATION_X, initialAnimateRotateX, rotateX, getTransitionConfigForProperty(PROP_INDEX_ROTATE_X), loop = true) } if (mask and MASK_ROTATE_Y != 0 && initialAnimateRotateY != rotateY) { - animateProperty("rotationY", DynamicAnimation.ROTATION_Y, initialAnimateRotateY, rotateY, loop = true) + animateProperty("rotationY", DynamicAnimation.ROTATION_Y, initialAnimateRotateY, rotateY, getTransitionConfigForProperty(PROP_INDEX_ROTATE_Y), loop = true) } if (mask and MASK_BORDER_RADIUS != 0 && initialAnimateBorderRadius != borderRadius) { - animateProperty("animateBorderRadius", null, initialAnimateBorderRadius, borderRadius, loop = true) + animateProperty("animateBorderRadius", null, initialAnimateBorderRadius, borderRadius, getTransitionConfigForProperty(PROP_INDEX_BORDER_RADIUS), loop = true) } if (mask and MASK_BACKGROUND_COLOR != 0 && initialAnimateBackgroundColor != backgroundColor) { - animateBackgroundColor(initialAnimateBackgroundColor, backgroundColor, loop = true) + animateBackgroundColor(initialAnimateBackgroundColor, backgroundColor, getTransitionConfigForProperty(PROP_INDEX_BACKGROUND_COLOR), loop = true) } } else { // No initial animation — set target values directly (skip non-animated) @@ -278,8 +349,8 @@ class EaseView(context: Context) : ReactViewGroup(context) { if (mask and MASK_BORDER_RADIUS != 0) setAnimateBorderRadius(borderRadius) if (mask and MASK_BACKGROUND_COLOR != 0) applyBackgroundColor(backgroundColor) } - } else if (transitionType == "none") { - // No transition — set values immediately, cancel running animations + } else if (!hasPerPropertyArrays() && transitionType == "none") { + // No transition (scalar) — set values immediately, cancel running animations cancelAllAnimations() if (mask and MASK_OPACITY != 0) this.alpha = opacity if (mask and MASK_TRANSLATE_X != 0) this.translationX = translateX @@ -295,52 +366,102 @@ class EaseView(context: Context) : ReactViewGroup(context) { } else { // Subsequent updates: animate changed properties (skip non-animated) if (prevOpacity != null && mask and MASK_OPACITY != 0 && prevOpacity != opacity) { - val from = getCurrentValue("alpha") - animateProperty("alpha", DynamicAnimation.ALPHA, from, opacity) + val config = getTransitionConfigForProperty(PROP_INDEX_OPACITY) + if (config.type == "none") { + this.alpha = opacity + } else { + val from = getCurrentValue("alpha") + animateProperty("alpha", DynamicAnimation.ALPHA, from, opacity, config) + } } if (prevTranslateX != null && mask and MASK_TRANSLATE_X != 0 && prevTranslateX != translateX) { - val from = getCurrentValue("translationX") - animateProperty("translationX", DynamicAnimation.TRANSLATION_X, from, translateX) + val config = getTransitionConfigForProperty(PROP_INDEX_TRANSLATE_X) + if (config.type == "none") { + this.translationX = translateX + } else { + val from = getCurrentValue("translationX") + animateProperty("translationX", DynamicAnimation.TRANSLATION_X, from, translateX, config) + } } if (prevTranslateY != null && mask and MASK_TRANSLATE_Y != 0 && prevTranslateY != translateY) { - val from = getCurrentValue("translationY") - animateProperty("translationY", DynamicAnimation.TRANSLATION_Y, from, translateY) + val config = getTransitionConfigForProperty(PROP_INDEX_TRANSLATE_Y) + if (config.type == "none") { + this.translationY = translateY + } else { + val from = getCurrentValue("translationY") + animateProperty("translationY", DynamicAnimation.TRANSLATION_Y, from, translateY, config) + } } if (prevScaleX != null && mask and MASK_SCALE_X != 0 && prevScaleX != scaleX) { - val from = getCurrentValue("scaleX") - animateProperty("scaleX", DynamicAnimation.SCALE_X, from, scaleX) + val config = getTransitionConfigForProperty(PROP_INDEX_SCALE_X) + if (config.type == "none") { + this.scaleX = scaleX + } else { + val from = getCurrentValue("scaleX") + animateProperty("scaleX", DynamicAnimation.SCALE_X, from, scaleX, config) + } } if (prevScaleY != null && mask and MASK_SCALE_Y != 0 && prevScaleY != scaleY) { - val from = getCurrentValue("scaleY") - animateProperty("scaleY", DynamicAnimation.SCALE_Y, from, scaleY) + val config = getTransitionConfigForProperty(PROP_INDEX_SCALE_Y) + if (config.type == "none") { + this.scaleY = scaleY + } else { + val from = getCurrentValue("scaleY") + animateProperty("scaleY", DynamicAnimation.SCALE_Y, from, scaleY, config) + } } if (prevRotate != null && mask and MASK_ROTATE != 0 && prevRotate != rotate) { - val from = getCurrentValue("rotation") - animateProperty("rotation", DynamicAnimation.ROTATION, from, rotate) + val config = getTransitionConfigForProperty(PROP_INDEX_ROTATE) + if (config.type == "none") { + this.rotation = rotate + } else { + val from = getCurrentValue("rotation") + animateProperty("rotation", DynamicAnimation.ROTATION, from, rotate, config) + } } if (prevRotateX != null && mask and MASK_ROTATE_X != 0 && prevRotateX != rotateX) { - val from = getCurrentValue("rotationX") - animateProperty("rotationX", DynamicAnimation.ROTATION_X, from, rotateX) + val config = getTransitionConfigForProperty(PROP_INDEX_ROTATE_X) + if (config.type == "none") { + this.rotationX = rotateX + } else { + val from = getCurrentValue("rotationX") + animateProperty("rotationX", DynamicAnimation.ROTATION_X, from, rotateX, config) + } } if (prevRotateY != null && mask and MASK_ROTATE_Y != 0 && prevRotateY != rotateY) { - val from = getCurrentValue("rotationY") - animateProperty("rotationY", DynamicAnimation.ROTATION_Y, from, rotateY) + val config = getTransitionConfigForProperty(PROP_INDEX_ROTATE_Y) + if (config.type == "none") { + this.rotationY = rotateY + } else { + val from = getCurrentValue("rotationY") + animateProperty("rotationY", DynamicAnimation.ROTATION_Y, from, rotateY, config) + } } if (prevBorderRadius != null && mask and MASK_BORDER_RADIUS != 0 && prevBorderRadius != borderRadius) { - val from = getCurrentValue("animateBorderRadius") - animateProperty("animateBorderRadius", null, from, borderRadius) + val config = getTransitionConfigForProperty(PROP_INDEX_BORDER_RADIUS) + if (config.type == "none") { + setAnimateBorderRadius(borderRadius) + } else { + val from = getCurrentValue("animateBorderRadius") + animateProperty("animateBorderRadius", null, from, borderRadius, config) + } } if (prevBackgroundColor != null && mask and MASK_BACKGROUND_COLOR != 0 && prevBackgroundColor != backgroundColor) { - animateBackgroundColor(getCurrentBackgroundColor(), backgroundColor) + val config = getTransitionConfigForProperty(PROP_INDEX_BACKGROUND_COLOR) + if (config.type == "none") { + applyBackgroundColor(backgroundColor) + } else { + animateBackgroundColor(getCurrentBackgroundColor(), backgroundColor, config) + } } } @@ -378,7 +499,7 @@ class EaseView(context: Context) : ReactViewGroup(context) { setBackgroundColor(color) } - private fun animateBackgroundColor(fromColor: Int, toColor: Int, loop: Boolean = false) { + private fun animateBackgroundColor(fromColor: Int, toColor: Int, config: TransitionConfig, loop: Boolean = false) { runningAnimators["backgroundColor"]?.cancel() val batchId = animationBatchId @@ -387,13 +508,15 @@ class EaseView(context: Context) : ReactViewGroup(context) { val animator = ValueAnimator.ofArgb(fromColor, toColor).apply { duration = transitionDuration.toLong() startDelay = transitionDelay + duration = config.duration.toLong() + interpolator = PathInterpolator( - transitionEasingBezier[0], transitionEasingBezier[1], - transitionEasingBezier[2], transitionEasingBezier[3] + config.easingBezier[0], config.easingBezier[1], + config.easingBezier[2], config.easingBezier[3] ) - if (loop && transitionLoop != "none") { + if (loop && config.loop != "none") { repeatCount = ValueAnimator.INFINITE - repeatMode = if (transitionLoop == "reverse") ValueAnimator.REVERSE else ValueAnimator.RESTART + repeatMode = if (config.loop == "reverse") ValueAnimator.REVERSE else ValueAnimator.RESTART } addUpdateListener { animation -> val color = animation.animatedValue as Int @@ -428,16 +551,17 @@ class EaseView(context: Context) : ReactViewGroup(context) { viewProperty: DynamicAnimation.ViewProperty?, fromValue: Float, toValue: Float, + config: TransitionConfig, loop: Boolean = false ) { - if (transitionType == "spring" && viewProperty != null) { - animateSpring(viewProperty, toValue) + if (config.type == "spring" && viewProperty != null) { + animateSpring(viewProperty, toValue, config) } else { - animateTiming(propertyName, fromValue, toValue, loop) + animateTiming(propertyName, fromValue, toValue, config, loop) } } - private fun animateTiming(propertyName: String, fromValue: Float, toValue: Float, loop: Boolean = false) { + private fun animateTiming(propertyName: String, fromValue: Float, toValue: Float, config: TransitionConfig, loop: Boolean = false) { cancelSpringForProperty(propertyName) runningAnimators[propertyName]?.cancel() @@ -447,13 +571,15 @@ class EaseView(context: Context) : ReactViewGroup(context) { val animator = ObjectAnimator.ofFloat(this, propertyName, fromValue, toValue).apply { duration = transitionDuration.toLong() startDelay = transitionDelay + duration = config.duration.toLong() + interpolator = PathInterpolator( - transitionEasingBezier[0], transitionEasingBezier[1], - transitionEasingBezier[2], transitionEasingBezier[3] + config.easingBezier[0], config.easingBezier[1], + config.easingBezier[2], config.easingBezier[3] ) - if (loop && transitionLoop != "none") { + if (loop && config.loop != "none") { repeatCount = ObjectAnimator.INFINITE - repeatMode = if (transitionLoop == "reverse") { + repeatMode = if (config.loop == "reverse") { ObjectAnimator.REVERSE } else { ObjectAnimator.RESTART @@ -484,7 +610,7 @@ class EaseView(context: Context) : ReactViewGroup(context) { animator.start() } - private fun animateSpring(viewProperty: DynamicAnimation.ViewProperty, toValue: Float) { + private fun animateSpring(viewProperty: DynamicAnimation.ViewProperty, toValue: Float, config: TransitionConfig) { cancelTimingForViewProperty(viewProperty) val existingSpring = runningSpringAnimations[viewProperty] @@ -496,13 +622,13 @@ class EaseView(context: Context) : ReactViewGroup(context) { val batchId = animationBatchId pendingBatchAnimationCount++ - val dampingRatio = (transitionDamping / (2.0f * sqrt(transitionStiffness * transitionMass))) + val dampingRatio = (config.damping / (2.0f * sqrt(config.stiffness * config.mass))) .coerceAtLeast(0.01f) val spring = SpringAnimation(this, viewProperty).apply { spring = SpringForce(toValue).apply { this.dampingRatio = dampingRatio - this.stiffness = transitionStiffness + this.stiffness = config.stiffness } addUpdateListener { _, _, _ -> // First update — enable hardware layer @@ -632,5 +758,13 @@ class EaseView(context: Context) : ReactViewGroup(context) { isFirstMount = true transitionLoop = "none" + + perPropertyTransitionTypes = null + perPropertyTransitionDurations = null + perPropertyTransitionDampings = null + perPropertyTransitionStiffnesses = null + perPropertyTransitionMasses = null + perPropertyTransitionLoops = null + perPropertyTransitionEasingBeziers = null } } diff --git a/android/src/main/java/com/ease/EaseViewManager.kt b/android/src/main/java/com/ease/EaseViewManager.kt index 5c426e5..fa5aafc 100644 --- a/android/src/main/java/com/ease/EaseViewManager.kt +++ b/android/src/main/java/com/ease/EaseViewManager.kt @@ -176,6 +176,70 @@ class EaseViewManager : ReactViewManager() { @ReactProp(name = "transitionDelay", defaultInt = 0) fun setTransitionDelay(view: EaseView, value: Int) { view.transitionDelay = value.toLong() + // --- Per-property transition arrays --- + + @ReactProp(name = "perPropertyTransitionTypes") + fun setPerPropertyTransitionTypes(view: EaseView, value: ReadableArray?) { + if (value != null && value.size() == 10) { + view.perPropertyTransitionTypes = Array(10) { value.getString(it) ?: "" } + } else { + view.perPropertyTransitionTypes = null + } + } + + @ReactProp(name = "perPropertyTransitionDurations") + fun setPerPropertyTransitionDurations(view: EaseView, value: ReadableArray?) { + if (value != null && value.size() == 10) { + view.perPropertyTransitionDurations = IntArray(10) { value.getInt(it) } + } else { + view.perPropertyTransitionDurations = null + } + } + + @ReactProp(name = "perPropertyTransitionDampings") + fun setPerPropertyTransitionDampings(view: EaseView, value: ReadableArray?) { + if (value != null && value.size() == 10) { + view.perPropertyTransitionDampings = FloatArray(10) { value.getDouble(it).toFloat() } + } else { + view.perPropertyTransitionDampings = null + } + } + + @ReactProp(name = "perPropertyTransitionStiffnesses") + fun setPerPropertyTransitionStiffnesses(view: EaseView, value: ReadableArray?) { + if (value != null && value.size() == 10) { + view.perPropertyTransitionStiffnesses = FloatArray(10) { value.getDouble(it).toFloat() } + } else { + view.perPropertyTransitionStiffnesses = null + } + } + + @ReactProp(name = "perPropertyTransitionMasses") + fun setPerPropertyTransitionMasses(view: EaseView, value: ReadableArray?) { + if (value != null && value.size() == 10) { + view.perPropertyTransitionMasses = FloatArray(10) { value.getDouble(it).toFloat() } + } else { + view.perPropertyTransitionMasses = null + } + } + + @ReactProp(name = "perPropertyTransitionLoops") + fun setPerPropertyTransitionLoops(view: EaseView, value: ReadableArray?) { + if (value != null && value.size() == 10) { + view.perPropertyTransitionLoops = Array(10) { value.getString(it) ?: "" } + } else { + view.perPropertyTransitionLoops = null + } + } + + @ReactProp(name = "perPropertyTransitionEasingBeziers") + fun setPerPropertyTransitionEasingBeziers(view: EaseView, value: ReadableArray?) { + if (value != null && value.size() == 40) { + view.perPropertyTransitionEasingBeziers = FloatArray(40) { value.getDouble(it).toFloat() } + } else { + view.perPropertyTransitionEasingBeziers = null + } + } // --- Border radius --- diff --git a/example/pnpm-lock.yaml b/example/pnpm-lock.yaml new file mode 100644 index 0000000..4b369d7 --- /dev/null +++ b/example/pnpm-lock.yaml @@ -0,0 +1,5986 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + react: + specifier: 19.2.0 + version: 19.2.0 + react-native: + specifier: 0.83.0 + version: 0.83.0(@babel/core@7.29.0)(@react-native-community/cli@20.0.0)(@react-native/metro-config@0.83.0(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.0) + react-native-reanimated: + specifier: ^4.2.2 + version: 4.2.2(react-native-worklets@0.7.4(@babel/core@7.29.0)(react-native@0.83.0(@babel/core@7.29.0)(@react-native-community/cli@20.0.0)(@react-native/metro-config@0.83.0(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.0))(react@19.2.0))(react-native@0.83.0(@babel/core@7.29.0)(@react-native-community/cli@20.0.0)(@react-native/metro-config@0.83.0(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.0))(react@19.2.0) + react-native-safe-area-context: + specifier: ^5.7.0 + version: 5.7.0(react-native@0.83.0(@babel/core@7.29.0)(@react-native-community/cli@20.0.0)(@react-native/metro-config@0.83.0(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.0))(react@19.2.0) + react-native-worklets: + specifier: ^0.7.4 + version: 0.7.4(@babel/core@7.29.0)(react-native@0.83.0(@babel/core@7.29.0)(@react-native-community/cli@20.0.0)(@react-native/metro-config@0.83.0(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.0))(react@19.2.0) + devDependencies: + '@babel/core': + specifier: ^7.25.2 + version: 7.29.0 + '@babel/preset-env': + specifier: ^7.25.3 + version: 7.29.0(@babel/core@7.29.0) + '@babel/runtime': + specifier: ^7.25.0 + version: 7.28.6 + '@react-native-community/cli': + specifier: 20.0.0 + version: 20.0.0 + '@react-native-community/cli-platform-android': + specifier: 20.0.0 + version: 20.0.0 + '@react-native-community/cli-platform-ios': + specifier: 20.0.0 + version: 20.0.0 + '@react-native/babel-preset': + specifier: 0.83.0 + version: 0.83.0(@babel/core@7.29.0) + '@react-native/metro-config': + specifier: 0.83.0 + version: 0.83.0(@babel/core@7.29.0) + '@react-native/typescript-config': + specifier: 0.83.0 + version: 0.83.0 + '@types/react': + specifier: ^19.2.0 + version: 19.2.14 + react-native-builder-bob: + specifier: ^0.40.18 + version: 0.40.18 + react-native-monorepo-config: + specifier: ^0.3.3 + version: 0.3.3 + +packages: + + '@ark/schema@0.56.0': + resolution: {integrity: sha512-ECg3hox/6Z/nLajxXqNhgPtNdHWC9zNsDyskwO28WinoFEnWow4IsERNz9AnXRhTZJnYIlAJ4uGn3nlLk65vZA==} + + '@ark/util@0.56.0': + resolution: {integrity: sha512-BghfRC8b9pNs3vBoDJhcta0/c1J1rsoS1+HgVUreMFPdhz/CRAKReAu57YEllNaSy98rWAdY1gE+gFup7OXpgA==} + + '@babel/code-frame@7.29.0': + resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.29.0': + resolution: {integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.29.0': + resolution: {integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.29.1': + resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-annotate-as-pure@7.27.3': + resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.28.6': + resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-create-class-features-plugin@7.28.6': + resolution: {integrity: sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-create-regexp-features-plugin@7.28.5': + resolution: {integrity: sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-define-polyfill-provider@0.6.7': + resolution: {integrity: sha512-6Fqi8MtQ/PweQ9xvux65emkLQ83uB+qAVtfHkC9UodyHMIZdxNI01HjLCLUtybElp2KY2XNE0nOgyP1E1vXw9w==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + '@babel/helper-globals@7.28.0': + resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-member-expression-to-functions@7.28.5': + resolution: {integrity: sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.28.6': + resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.28.6': + resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-optimise-call-expression@7.27.1': + resolution: {integrity: sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-plugin-utils@7.28.6': + resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==} + engines: {node: '>=6.9.0'} + + '@babel/helper-remap-async-to-generator@7.27.1': + resolution: {integrity: sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-replace-supers@7.28.6': + resolution: {integrity: sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-skip-transparent-expression-wrappers@7.27.1': + resolution: {integrity: sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.27.1': + resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-wrap-function@7.28.6': + resolution: {integrity: sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.28.6': + resolution: {integrity: sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.29.0': + resolution: {integrity: sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5': + resolution: {integrity: sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1': + resolution: {integrity: sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1': + resolution: {integrity: sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1': + resolution: {integrity: sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.13.0 + + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.6': + resolution: {integrity: sha512-a0aBScVTlNaiUe35UtfxAN7A/tehvvG4/ByO6+46VPKTRSlfnAFsgKy0FUh+qAkQrDTmhDkT+IBOKlOoMUxQ0g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-proposal-export-default-from@7.27.1': + resolution: {integrity: sha512-hjlsMBl1aJc5lp8MoCDEZCiYzlgdRAShOjAfRw6X+GlpLpUPU7c3XNLsKFZbQk/1cRzBlJ7CXg3xJAJMrFa1Uw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2': + resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-async-generators@7.8.4': + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-bigint@7.8.3': + resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-class-properties@7.12.13': + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-class-static-block@7.14.5': + resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-dynamic-import@7.8.3': + resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-export-default-from@7.28.6': + resolution: {integrity: sha512-Svlx1fjJFnNz0LZeUaybRukSxZI3KkpApUmIRzEdXC5k8ErTOz0OD0kNrICi5Vc3GlpP5ZCeRyRO+mfWTSz+iQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-flow@7.28.6': + resolution: {integrity: sha512-D+OrJumc9McXNEBI/JmFnc/0uCM2/Y3PEBG3gfV3QIYkKv5pvnpzFrl1kYCrcHJP8nOeFB/SHi1IHz29pNGuew==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-assertions@7.28.6': + resolution: {integrity: sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-attributes@7.28.6': + resolution: {integrity: sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-meta@7.10.4': + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-json-strings@7.8.3': + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-jsx@7.28.6': + resolution: {integrity: sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-logical-assignment-operators@7.10.4': + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3': + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-numeric-separator@7.10.4': + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-object-rest-spread@7.8.3': + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3': + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-optional-chaining@7.8.3': + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-private-property-in-object@7.14.5': + resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-top-level-await@7.14.5': + resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-typescript@7.28.6': + resolution: {integrity: sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-unicode-sets-regex@7.18.6': + resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-arrow-functions@7.27.1': + resolution: {integrity: sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-async-generator-functions@7.29.0': + resolution: {integrity: sha512-va0VdWro4zlBr2JsXC+ofCPB2iG12wPtVGTWFx2WLDOM3nYQZZIGP82qku2eW/JR83sD+k2k+CsNtyEbUqhU6w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-async-to-generator@7.28.6': + resolution: {integrity: sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-block-scoped-functions@7.27.1': + resolution: {integrity: sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-block-scoping@7.28.6': + resolution: {integrity: sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-class-properties@7.27.1': + resolution: {integrity: sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-class-properties@7.28.6': + resolution: {integrity: sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-class-static-block@7.28.6': + resolution: {integrity: sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.12.0 + + '@babel/plugin-transform-classes@7.28.4': + resolution: {integrity: sha512-cFOlhIYPBv/iBoc+KS3M6et2XPtbT2HiCRfBXWtfpc9OAyostldxIf9YAYB6ypURBBbx+Qv6nyrLzASfJe+hBA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-classes@7.28.6': + resolution: {integrity: sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-computed-properties@7.28.6': + resolution: {integrity: sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-destructuring@7.28.5': + resolution: {integrity: sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-dotall-regex@7.28.6': + resolution: {integrity: sha512-SljjowuNKB7q5Oayv4FoPzeB74g3QgLt8IVJw9ADvWy3QnUb/01aw8I4AVv8wYnPvQz2GDDZ/g3GhcNyDBI4Bg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-duplicate-keys@7.27.1': + resolution: {integrity: sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.29.0': + resolution: {integrity: sha512-zBPcW2lFGxdiD8PUnPwJjag2J9otbcLQzvbiOzDxpYXyCuYX9agOwMPGn1prVH0a4qzhCKu24rlH4c1f7yA8rw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-dynamic-import@7.27.1': + resolution: {integrity: sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-explicit-resource-management@7.28.6': + resolution: {integrity: sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-exponentiation-operator@7.28.6': + resolution: {integrity: sha512-WitabqiGjV/vJ0aPOLSFfNY1u9U3R7W36B03r5I2KoNix+a3sOhJ3pKFB3R5It9/UiK78NiO0KE9P21cMhlPkw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-export-namespace-from@7.27.1': + resolution: {integrity: sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-flow-strip-types@7.27.1': + resolution: {integrity: sha512-G5eDKsu50udECw7DL2AcsysXiQyB7Nfg521t2OAJ4tbfTJ27doHLeF/vlI1NZGlLdbb/v+ibvtL1YBQqYOwJGg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-for-of@7.27.1': + resolution: {integrity: sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-function-name@7.27.1': + resolution: {integrity: sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-json-strings@7.28.6': + resolution: {integrity: sha512-Nr+hEN+0geQkzhbdgQVPoqr47lZbm+5fCUmO70722xJZd0Mvb59+33QLImGj6F+DkK3xgDi1YVysP8whD6FQAw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-literals@7.27.1': + resolution: {integrity: sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-logical-assignment-operators@7.28.6': + resolution: {integrity: sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-member-expression-literals@7.27.1': + resolution: {integrity: sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-amd@7.27.1': + resolution: {integrity: sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-commonjs@7.28.6': + resolution: {integrity: sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-systemjs@7.29.0': + resolution: {integrity: sha512-PrujnVFbOdUpw4UHiVwKvKRLMMic8+eC0CuNlxjsyZUiBjhFdPsewdXCkveh2KqBA9/waD0W1b4hXSOBQJezpQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-umd@7.27.1': + resolution: {integrity: sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-named-capturing-groups-regex@7.29.0': + resolution: {integrity: sha512-1CZQA5KNAD6ZYQLPw7oi5ewtDNxH/2vuCh+6SmvgDfhumForvs8a1o9n0UrEoBD8HU4djO2yWngTQlXl1NDVEQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-new-target@7.27.1': + resolution: {integrity: sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-nullish-coalescing-operator@7.27.1': + resolution: {integrity: sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-nullish-coalescing-operator@7.28.6': + resolution: {integrity: sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-numeric-separator@7.28.6': + resolution: {integrity: sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-object-rest-spread@7.28.6': + resolution: {integrity: sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-object-super@7.27.1': + resolution: {integrity: sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-optional-catch-binding@7.28.6': + resolution: {integrity: sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-optional-chaining@7.27.1': + resolution: {integrity: sha512-BQmKPPIuc8EkZgNKsv0X4bPmOoayeu4F1YCwx2/CfmDSXDbp7GnzlUH+/ul5VGfRg1AoFPsrIThlEBj2xb4CAg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-optional-chaining@7.28.6': + resolution: {integrity: sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-parameters@7.27.7': + resolution: {integrity: sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-private-methods@7.28.6': + resolution: {integrity: sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-private-property-in-object@7.28.6': + resolution: {integrity: sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-property-literals@7.27.1': + resolution: {integrity: sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-display-name@7.28.0': + resolution: {integrity: sha512-D6Eujc2zMxKjfa4Zxl4GHMsmhKKZ9VpcqIchJLvwTxad9zWIYulwYItBovpDOoNLISpcZSXoDJ5gaGbQUDqViA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-development@7.27.1': + resolution: {integrity: sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-self@7.27.1': + resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-source@7.27.1': + resolution: {integrity: sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx@7.28.6': + resolution: {integrity: sha512-61bxqhiRfAACulXSLd/GxqmAedUSrRZIu/cbaT18T1CetkTmtDN15it7i80ru4DVqRK1WMxQhXs+Lf9kajm5Ow==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-pure-annotations@7.27.1': + resolution: {integrity: sha512-JfuinvDOsD9FVMTHpzA/pBLisxpv1aSf+OIV8lgH3MuWrks19R27e6a6DipIg4aX1Zm9Wpb04p8wljfKrVSnPA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-regenerator@7.29.0': + resolution: {integrity: sha512-FijqlqMA7DmRdg/aINBSs04y8XNTYw/lr1gJ2WsmBnnaNw1iS43EPkJW+zK7z65auG3AWRFXWj+NcTQwYptUog==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-regexp-modifiers@7.28.6': + resolution: {integrity: sha512-QGWAepm9qxpaIs7UM9FvUSnCGlb8Ua1RhyM4/veAxLwt3gMat/LSGrZixyuj4I6+Kn9iwvqCyPTtbdxanYoWYg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-reserved-words@7.27.1': + resolution: {integrity: sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-runtime@7.29.0': + resolution: {integrity: sha512-jlaRT5dJtMaMCV6fAuLbsQMSwz/QkvaHOHOSXRitGGwSpR1blCY4KUKoyP2tYO8vJcqYe8cEj96cqSztv3uF9w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-shorthand-properties@7.27.1': + resolution: {integrity: sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-spread@7.28.6': + resolution: {integrity: sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-sticky-regex@7.27.1': + resolution: {integrity: sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-strict-mode@7.27.1': + resolution: {integrity: sha512-cdA1TyX9NfOaV8PILyNSrzJxXnjk4UeAgSwSLDCepfOg9AlxCg5al0KWsFh0ZJRzp6k5gwpSlJ4auWT+gx46ig==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-template-literals@7.27.1': + resolution: {integrity: sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-typeof-symbol@7.27.1': + resolution: {integrity: sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-typescript@7.28.6': + resolution: {integrity: sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-escapes@7.27.1': + resolution: {integrity: sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-property-regex@7.28.6': + resolution: {integrity: sha512-4Wlbdl/sIZjzi/8St0evF0gEZrgOswVO6aOzqxh1kDZOl9WmLrHq2HtGhnOJZmHZYKP8WZ1MDLCt5DAWwRo57A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-regex@7.27.1': + resolution: {integrity: sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-sets-regex@7.28.6': + resolution: {integrity: sha512-/wHc/paTUmsDYN7SZkpWxogTOBNnlx7nBQYfy6JJlCT7G3mVhltk3e++N7zV0XfgGsrqBxd4rJQt9H16I21Y1Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/preset-env@7.29.0': + resolution: {integrity: sha512-fNEdfc0yi16lt6IZo2Qxk3knHVdfMYX33czNb4v8yWhemoBhibCpQK/uYHtSKIiO+p/zd3+8fYVXhQdOVV608w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/preset-modules@0.1.6-no-external-plugins': + resolution: {integrity: sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==} + peerDependencies: + '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 + + '@babel/preset-react@7.28.5': + resolution: {integrity: sha512-Z3J8vhRq7CeLjdC58jLv4lnZ5RKFUJWqH5emvxmv9Hv3BD1T9R/Im713R4MTKwvFaV74ejZ3sM01LyEKk4ugNQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/preset-typescript@7.27.1': + resolution: {integrity: sha512-l7WfQfX0WK4M0v2RudjuQK4u99BS6yLHYEmdtVPP7lKV013zr9DygFuWNlnbvQ9LR+LS0Egz/XAvGx5U9MX0fQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/preset-typescript@7.28.5': + resolution: {integrity: sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/runtime@7.28.6': + resolution: {integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==} + engines: {node: '>=6.9.0'} + + '@babel/template@7.28.6': + resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.29.0': + resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.29.0': + resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} + engines: {node: '>=6.9.0'} + + '@hapi/hoek@9.3.0': + resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} + + '@hapi/topo@5.1.0': + resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==} + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@isaacs/ttlcache@1.4.1': + resolution: {integrity: sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==} + engines: {node: '>=12'} + + '@istanbuljs/load-nyc-config@1.1.0': + resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} + engines: {node: '>=8'} + + '@istanbuljs/schema@0.1.3': + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + + '@jest/create-cache-key-function@29.7.0': + resolution: {integrity: sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/environment@29.7.0': + resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/fake-timers@29.7.0': + resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/schemas@29.6.3': + resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/transform@29.7.0': + resolution: {integrity: sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/types@29.6.3': + resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/source-map@0.3.11': + resolution: {integrity: sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@react-native-community/cli-clean@20.0.0': + resolution: {integrity: sha512-YmdNRcT+Dp8lC7CfxSDIfPMbVPEXVFzBH62VZNbYGxjyakqAvoQUFTYPgM2AyFusAr4wDFbDOsEv88gCDwR3ig==} + + '@react-native-community/cli-config-android@20.0.0': + resolution: {integrity: sha512-asv60qYCnL1v0QFWcG9r1zckeFlKG+14GGNyPXY72Eea7RX5Cxdx8Pb6fIPKroWH1HEWjYH9KKHksMSnf9FMKw==} + + '@react-native-community/cli-config-apple@20.0.0': + resolution: {integrity: sha512-PS1gNOdpeQ6w7dVu1zi++E+ix2D0ZkGC2SQP6Y/Qp002wG4se56esLXItYiiLrJkhH21P28fXdmYvTEkjSm9/Q==} + + '@react-native-community/cli-config@20.0.0': + resolution: {integrity: sha512-5Ky9ceYuDqG62VIIpbOmkg8Lybj2fUjf/5wK4UO107uRqejBgNgKsbGnIZgEhREcaSEOkujWrroJ9gweueLfBg==} + + '@react-native-community/cli-doctor@20.0.0': + resolution: {integrity: sha512-cPHspi59+Fy41FDVxt62ZWoicCZ1o34k8LAl64NVSY0lwPl+CEi78jipXJhtfkVqSTetloA8zexa/vSAcJy57Q==} + + '@react-native-community/cli-platform-android@20.0.0': + resolution: {integrity: sha512-th3ji1GRcV6ACelgC0wJtt9daDZ+63/52KTwL39xXGoqczFjml4qERK90/ppcXU0Ilgq55ANF8Pr+UotQ2AB/A==} + + '@react-native-community/cli-platform-apple@20.0.0': + resolution: {integrity: sha512-rZZCnAjUHN1XBgiWTAMwEKpbVTO4IHBSecdd1VxJFeTZ7WjmstqA6L/HXcnueBgxrzTCRqvkRIyEQXxC1OfhGw==} + + '@react-native-community/cli-platform-ios@20.0.0': + resolution: {integrity: sha512-Z35M+4gUJgtS4WqgpKU9/XYur70nmj3Q65c9USyTq6v/7YJ4VmBkmhC9BticPs6wuQ9Jcv0NyVCY0Wmh6kMMYw==} + + '@react-native-community/cli-server-api@20.0.0': + resolution: {integrity: sha512-Ves21bXtjUK3tQbtqw/NdzpMW1vR2HvYCkUQ/MXKrJcPjgJnXQpSnTqHXz6ZdBlMbbwLJXOhSPiYzxb5/v4CDg==} + + '@react-native-community/cli-tools@20.0.0': + resolution: {integrity: sha512-akSZGxr1IajJ8n0YCwQoA3DI0HttJ0WB7M3nVpb0lOM+rJpsBN7WG5Ft+8ozb6HyIPX+O+lLeYazxn5VNG/Xhw==} + + '@react-native-community/cli-types@20.0.0': + resolution: {integrity: sha512-7J4hzGWOPTBV1d30Pf2NidV+bfCWpjfCOiGO3HUhz1fH4MvBM0FbbBmE9LE5NnMz7M8XSRSi68ZGYQXgLBB2Qw==} + + '@react-native-community/cli@20.0.0': + resolution: {integrity: sha512-/cMnGl5V1rqnbElY1Fvga1vfw0d3bnqiJLx2+2oh7l9ulnXfVRWb5tU2kgBqiMxuDOKA+DQoifC9q/tvkj5K2w==} + engines: {node: '>=18'} + hasBin: true + + '@react-native/assets-registry@0.83.0': + resolution: {integrity: sha512-EmGSKDvmnEnBrTK75T+0Syt6gy/HACOTfziw5+392Kr1Bb28Rv26GyOIkvptnT+bb2VDHU0hx9G0vSy5/S3rmQ==} + engines: {node: '>= 20.19.4'} + + '@react-native/babel-plugin-codegen@0.83.0': + resolution: {integrity: sha512-H5K0hnv9EhcenojZb9nUMIKPvHZ7ba9vpCyQIeGJmUTDYwZqjmXXyH73+uZo+GHjCIq1n0eF/soC5HJQzalh/Q==} + engines: {node: '>= 20.19.4'} + + '@react-native/babel-preset@0.83.0': + resolution: {integrity: sha512-v20aTae9+aergUgRQSiy3CLqRSJu5VrHLpPpyYcAkTJ2JWTbtTlKfYuEw0V/WMFpeYZnZ7IVtu/6gTISVV74UQ==} + engines: {node: '>= 20.19.4'} + peerDependencies: + '@babel/core': '*' + + '@react-native/codegen@0.83.0': + resolution: {integrity: sha512-3fvMi/pSJHhikjwMZQplU4Ar9ANoR2GSBxotbkKIMI6iNduh+ln1FTvB2me69FA68aHtVZOO+cO+QpGCcvgaMA==} + engines: {node: '>= 20.19.4'} + peerDependencies: + '@babel/core': '*' + + '@react-native/community-cli-plugin@0.83.0': + resolution: {integrity: sha512-bJD5pLURgKY2YK0R6gUsFWHiblSAFt1Xyc2fsyCL8XBnB7kJfVhLAKGItk6j1QZbwm1Io41ekZxBmZdyQqIDrg==} + engines: {node: '>= 20.19.4'} + peerDependencies: + '@react-native-community/cli': '*' + '@react-native/metro-config': '*' + peerDependenciesMeta: + '@react-native-community/cli': + optional: true + '@react-native/metro-config': + optional: true + + '@react-native/debugger-frontend@0.83.0': + resolution: {integrity: sha512-7XVbkH8nCjLKLe8z5DS37LNP62/QNNya/YuLlVoLfsiB54nR/kNZij5UU7rS0npAZ3WN7LR0anqLlYnzDd0JHA==} + engines: {node: '>= 20.19.4'} + + '@react-native/debugger-shell@0.83.0': + resolution: {integrity: sha512-rJJxRRLLsKW+cqd0ALSBoqwL5SQTmwpd5SGl6rq9sY+fInCUKfkLEIc5HWQ0ppqoPyDteQVWbQ3a5VN84aJaNg==} + engines: {node: '>= 20.19.4'} + + '@react-native/dev-middleware@0.83.0': + resolution: {integrity: sha512-HWn42tbp0h8RWttua6d6PjseaSr3IdwkaoqVxhiM9kVDY7Ro00eO7tdlVgSzZzhIibdVS2b2C3x+sFoWhag1fA==} + engines: {node: '>= 20.19.4'} + + '@react-native/gradle-plugin@0.83.0': + resolution: {integrity: sha512-BXZRmfsbgPhEPkrRPjk2njA2AzhSelBqhuoklnv3DdLTdxaRjKYW+LW0zpKo1k3qPKj7kG1YGI3miol6l1GB5g==} + engines: {node: '>= 20.19.4'} + + '@react-native/js-polyfills@0.83.0': + resolution: {integrity: sha512-cVB9BMqlfbQR0v4Wxi5M2yDhZoKiNqWgiEXpp7ChdZIXI0SEnj8WwLwE3bDkyOfF8tCHdytpInXyg/al2O+dLQ==} + engines: {node: '>= 20.19.4'} + + '@react-native/metro-babel-transformer@0.83.0': + resolution: {integrity: sha512-hB5kpR5Ho9l9xKuh5uHZEIFqnuaW8T7rDYwqf1j0xvTZu88KwaHAXya2IpDZsjlWzVMCl50cAwPkVZOlEOfJvw==} + engines: {node: '>= 20.19.4'} + peerDependencies: + '@babel/core': '*' + + '@react-native/metro-config@0.83.0': + resolution: {integrity: sha512-7mWZNZOJJLMJ8adBrAgAXcwtyn8PtPjAGavK8k3/mtsWYm79ncf5PD8D9puh6wBHCYwPu2ff/l23nNV8JsqLyg==} + engines: {node: '>= 20.19.4'} + + '@react-native/normalize-colors@0.83.0': + resolution: {integrity: sha512-DG1ELOqQ6RS82R1zEUGTWa/pfSPOf+vwAnQB7Ao1vRuhW/xdd2OPQJyqx5a5QWMYpGrlkCb7ERxEVX6p2QODCA==} + + '@react-native/typescript-config@0.83.0': + resolution: {integrity: sha512-8IcgamT0qoBDL3D8Ho6YHkQrxUMf3fKHkRd6MYDjVKNamz0XtfXNLY/FNnUOolx1HbgMkkwKFcbP3AbIKFxirQ==} + + '@react-native/virtualized-lists@0.83.0': + resolution: {integrity: sha512-AVnDppwPidQrPrzA4ETr4o9W+40yuijg3EVgFt2hnMldMZkqwPRrgJL2GSreQjCYe1NfM5Yn4Egyy4Kd0yp4Lw==} + engines: {node: '>= 20.19.4'} + peerDependencies: + '@types/react': ^19.2.0 + react: '*' + react-native: '*' + peerDependenciesMeta: + '@types/react': + optional: true + + '@sideway/address@4.1.5': + resolution: {integrity: sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==} + + '@sideway/formula@3.0.1': + resolution: {integrity: sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==} + + '@sideway/pinpoint@2.0.0': + resolution: {integrity: sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==} + + '@sinclair/typebox@0.27.10': + resolution: {integrity: sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==} + + '@sinonjs/commons@3.0.1': + resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} + + '@sinonjs/fake-timers@10.3.0': + resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} + + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + + '@types/babel__generator@7.27.0': + resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} + + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + + '@types/babel__traverse@7.28.0': + resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} + + '@types/graceful-fs@4.1.9': + resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} + + '@types/istanbul-lib-coverage@2.0.6': + resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} + + '@types/istanbul-lib-report@3.0.3': + resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} + + '@types/istanbul-reports@3.0.4': + resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} + + '@types/node@25.5.0': + resolution: {integrity: sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==} + + '@types/react@19.2.14': + resolution: {integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==} + + '@types/stack-utils@2.0.3': + resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + + '@types/yargs-parser@21.0.3': + resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} + + '@types/yargs@17.0.35': + resolution: {integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==} + + '@vscode/sudo-prompt@9.3.2': + resolution: {integrity: sha512-gcXoCN00METUNFeQOFJ+C9xUI0DKB+0EGMVg7wbVYRHBw2Eq3fKisDZOkRdOz3kqXRKOENMfShPOmypw1/8nOw==} + + abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + + accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + + accepts@2.0.0: + resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} + engines: {node: '>= 0.6'} + + acorn@8.16.0: + resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} + engines: {node: '>=0.4.0'} + hasBin: true + + agent-base@7.1.4: + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} + engines: {node: '>= 14'} + + aggregate-error@3.1.0: + resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} + engines: {node: '>=8'} + + anser@1.4.10: + resolution: {integrity: sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==} + + ansi-fragments@0.2.1: + resolution: {integrity: sha512-DykbNHxuXQwUDRv5ibc2b0x7uw7wmwOGLBUd5RmaQ5z8Lhx19vwvKV+FAsM5rEA6dEcHxX+/Ad5s9eF2k2bB+w==} + + ansi-regex@4.1.1: + resolution: {integrity: sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==} + engines: {node: '>=6'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.2.2: + resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + engines: {node: '>=12'} + + ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + + ansi-styles@6.2.3: + resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} + engines: {node: '>=12'} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + appdirsjs@1.2.7: + resolution: {integrity: sha512-Quji6+8kLBC3NnBeo14nPDq0+2jUs5s3/xEye+udFHumHhRk4M7aAMXp/PBJqkKYGuuyR9M/6Dq7d2AViiGmhw==} + + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + arkregex@0.0.5: + resolution: {integrity: sha512-ncYjBdLlh5/QnVsAA8De16Tc9EqmYM7y/WU9j+236KcyYNUXogpz3sC4ATIZYzzLxwI+0sEOaQLEmLmRleaEXw==} + + arktype@2.2.0: + resolution: {integrity: sha512-t54MZ7ti5BhOEvzEkgKnWvqj+UbDfWig+DHr5I34xatymPusKLS0lQpNJd8M6DzmIto2QGszHfNKoFIT8tMCZQ==} + + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + + asap@2.0.6: + resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} + + astral-regex@1.0.0: + resolution: {integrity: sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==} + engines: {node: '>=4'} + + async-limiter@1.0.1: + resolution: {integrity: sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==} + + babel-jest@29.7.0: + resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.8.0 + + babel-plugin-istanbul@6.1.1: + resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} + engines: {node: '>=8'} + + babel-plugin-jest-hoist@29.6.3: + resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + babel-plugin-polyfill-corejs2@0.4.16: + resolution: {integrity: sha512-xaVwwSfebXf0ooE11BJovZYKhFjIvQo7TsyVpETuIeH2JHv0k/T6Y5j22pPTvqYqmpkxdlPAJlyJ0tfOJAoMxw==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-polyfill-corejs3@0.13.0: + resolution: {integrity: sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-polyfill-corejs3@0.14.1: + resolution: {integrity: sha512-ENp89vM9Pw4kv/koBb5N2f9bDZsR0hpf3BdPMOg/pkS3pwO4dzNnQZVXtBbeyAadgm865DmQG2jMMLqmZXvuCw==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-polyfill-regenerator@0.6.7: + resolution: {integrity: sha512-OTYbUlSwXhNgr4g6efMZgsO8//jA61P7ZbRX3iTT53VON8l+WQS8IAUEVo4a4cWknrg2W8Cj4gQhRYNCJ8GkAA==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-syntax-hermes-parser@0.28.1: + resolution: {integrity: sha512-meT17DOuUElMNsL5LZN56d+KBp22hb0EfxWfuPUeoSi54e40v1W4C2V36P75FpsH9fVEfDKpw5Nnkahc8haSsQ==} + + babel-plugin-syntax-hermes-parser@0.32.0: + resolution: {integrity: sha512-m5HthL++AbyeEA2FcdwOLfVFvWYECOBObLHNqdR8ceY4TsEdn4LdX2oTvbB2QJSSElE2AWA/b2MXZ/PF/CqLZg==} + + babel-plugin-transform-flow-enums@0.0.2: + resolution: {integrity: sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ==} + + babel-preset-current-node-syntax@1.2.0: + resolution: {integrity: sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==} + peerDependencies: + '@babel/core': ^7.0.0 || ^8.0.0-0 + + babel-preset-jest@29.6.3: + resolution: {integrity: sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.0.0 + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + baseline-browser-mapping@2.10.8: + resolution: {integrity: sha512-PCLz/LXGBsNTErbtB6i5u4eLpHeMfi93aUv5duMmj6caNu6IphS4q6UevDnL36sZQv9lrP11dbPKGMaXPwMKfQ==} + engines: {node: '>=6.0.0'} + hasBin: true + + bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + + body-parser@1.20.4: + resolution: {integrity: sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + brace-expansion@1.1.12: + resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} + + brace-expansion@2.0.2: + resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browserslist@4.28.1: + resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + bser@2.1.1: + resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + + bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + + camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + + caniuse-lite@1.0.30001779: + resolution: {integrity: sha512-U5og2PN7V4DMgF50YPNtnZJGWVLFjjsN3zb6uMT5VGYIewieDj1upwfuVNXf4Kor+89c3iCRJnSzMD5LmTvsfA==} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chrome-launcher@0.15.2: + resolution: {integrity: sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==} + engines: {node: '>=12.13.0'} + hasBin: true + + chromium-edge-launcher@0.2.0: + resolution: {integrity: sha512-JfJjUnq25y9yg4FABRRVPmBGWPZZi+AQXT4mxupb67766/0UlhG8PAZCz6xzEMXTbW3CsSoE8PcCWA49n35mKg==} + + ci-info@2.0.0: + resolution: {integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==} + + ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + + clean-stack@2.2.0: + resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} + engines: {node: '>=6'} + + cli-cursor@3.1.0: + resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} + engines: {node: '>=8'} + + cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} + + cliui@6.0.0: + resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + clone@1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + + color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + colorette@1.4.0: + resolution: {integrity: sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==} + + command-exists@1.2.9: + resolution: {integrity: sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==} + + commander@12.1.0: + resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} + engines: {node: '>=18'} + + commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + + commander@9.5.0: + resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} + engines: {node: ^12.20.0 || >=14} + + compressible@2.0.18: + resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} + engines: {node: '>= 0.6'} + + compression@1.8.1: + resolution: {integrity: sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==} + engines: {node: '>= 0.8.0'} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + connect@3.7.0: + resolution: {integrity: sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==} + engines: {node: '>= 0.10.0'} + + content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + core-js-compat@3.48.0: + resolution: {integrity: sha512-OM4cAF3D6VtH/WkLtWvyNC56EZVXsZdU3iqaMG2B4WvYrlqU831pc4UtG5yp0sE9z8Y02wVN7PjW5Zf9Gt0f1Q==} + + cosmiconfig@9.0.1: + resolution: {integrity: sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + + dayjs@1.11.20: + resolution: {integrity: sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ==} + + debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decamelize@1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + + dedent@0.7.0: + resolution: {integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==} + + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + + defaults@1.0.4: + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + + del@6.1.1: + resolution: {integrity: sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==} + engines: {node: '>=10'} + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + + electron-to-chromium@1.5.313: + resolution: {integrity: sha512-QBMrTWEf00GXZmJyx2lbYD45jpI3TUFnNIzJ5BBc8piGUDwMPa1GV6HJWTZVvY/eiN3fSopl7NRbgGp9sZ9LTA==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + + encodeurl@2.0.0: + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} + engines: {node: '>= 0.8'} + + end-of-stream@1.4.5: + resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} + + env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + + envinfo@7.21.0: + resolution: {integrity: sha512-Lw7I8Zp5YKHFCXL7+Dz95g4CcbMEpgvqZNNq3AmlT5XAV6CgAAk6gyAMqn2zjw08K9BHfcNuKrMiCPLByGafow==} + engines: {node: '>=4'} + hasBin: true + + error-ex@1.3.4: + resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} + + error-stack-parser@2.1.4: + resolution: {integrity: sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==} + + errorhandler@1.5.2: + resolution: {integrity: sha512-kNAL7hESndBCrWwS72QyV3IVOTrVmj9D062FV5BQswNL5zEdeRmz/WJFyh6Aj/plvvSOrzddkxW57HgkZcR9Fw==} + engines: {node: '>= 0.8'} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + escape-string-regexp@2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + escape-string-regexp@5.0.0: + resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} + engines: {node: '>=12'} + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + + event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + + execa@4.1.0: + resolution: {integrity: sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==} + engines: {node: '>=10'} + + execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + + exponential-backoff@3.1.3: + resolution: {integrity: sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==} + + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-xml-parser@4.5.4: + resolution: {integrity: sha512-jE8ugADnYOBsu1uaoayVl1tVKAMNOXyjwvv2U6udEA2ORBhDooJDWoGxTkhd4Qn4yh59JVVt/pKXtjPwx9OguQ==} + hasBin: true + + fastq@1.20.1: + resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} + + fb-dotslash@0.5.8: + resolution: {integrity: sha512-XHYLKk9J4BupDxi9bSEhkfss0m+Vr9ChTrjhf9l2iw3jB5C7BnY4GVPoMcqbrTutsKJso6yj2nAB6BI/F2oZaA==} + engines: {node: '>=20'} + hasBin: true + + fb-watchman@2.0.2: + resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + finalhandler@1.1.2: + resolution: {integrity: sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==} + engines: {node: '>= 0.8'} + + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flow-enums-runtime@0.0.6: + resolution: {integrity: sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==} + + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + + fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + + fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + + fs-extra@8.1.0: + resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} + engines: {node: '>=6 <7 || >=8'} + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-package-type@0.1.0: + resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} + engines: {node: '>=8.0.0'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + get-stream@5.2.0: + resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} + engines: {node: '>=8'} + + get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob@10.5.0: + resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==} + 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 + hasBin: true + + glob@7.2.3: + resolution: {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 + + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + hermes-compiler@0.14.0: + resolution: {integrity: sha512-clxa193o+GYYwykWVFfpHduCATz8fR5jvU7ngXpfKHj+E9hr9vjLNtdLSEe8MUbObvVexV3wcyxQ00xTPIrB1Q==} + + hermes-estree@0.28.1: + resolution: {integrity: sha512-w3nxl/RGM7LBae0v8LH2o36+8VqwOZGv9rX1wyoWT6YaKZLqpJZ0YQ5P0LVr3tuRpf7vCx0iIG4i/VmBJejxTQ==} + + hermes-estree@0.32.0: + resolution: {integrity: sha512-KWn3BqnlDOl97Xe1Yviur6NbgIZ+IP+UVSpshlZWkq+EtoHg6/cwiDj/osP9PCEgFE15KBm1O55JRwbMEm5ejQ==} + + hermes-estree@0.33.3: + resolution: {integrity: sha512-6kzYZHCk8Fy1Uc+t3HGYyJn3OL4aeqKLTyina4UFtWl8I0kSL7OmKThaiX+Uh2f8nGw3mo4Ifxg0M5Zk3/Oeqg==} + + hermes-parser@0.28.1: + resolution: {integrity: sha512-nf8o+hE8g7UJWParnccljHumE9Vlq8F7MqIdeahl+4x0tvCUJYRrT0L7h0MMg/X9YJmkNwsfbaNNrzPtFXOscg==} + + hermes-parser@0.32.0: + resolution: {integrity: sha512-g4nBOWFpuiTqjR3LZdRxKUkij9iyveWeuks7INEsMX741f3r9xxrOe8TeQfUxtda0eXmiIFiMQzoeSQEno33Hw==} + + hermes-parser@0.33.3: + resolution: {integrity: sha512-Yg3HgaG4CqgyowtYjX/FsnPAuZdHOqSMtnbpylbptsQ9nwwSKsy6uRWcGO5RK0EqiX12q8HvDWKgeAVajRO5DA==} + + http-errors@2.0.1: + resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} + engines: {node: '>= 0.8'} + + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + + human-signals@1.1.1: + resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==} + engines: {node: '>=8.12.0'} + + human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + image-size@1.2.1: + resolution: {integrity: sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw==} + engines: {node: '>=16.x'} + hasBin: true + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + + inflight@1.0.6: + resolution: {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. + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + invariant@2.2.4: + resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} + + is-absolute@1.0.0: + resolution: {integrity: sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==} + engines: {node: '>=0.10.0'} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + + is-docker@2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@2.0.0: + resolution: {integrity: sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==} + engines: {node: '>=4'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-git-dirty@2.0.2: + resolution: {integrity: sha512-U3YCo+GKR/rDsY7r0v/LBICbQwsx859tDQnAT+v0E/zCDeWbQ1TUt1FtyExeyik7VIJlYOLHCIifLdz71HDalg==} + engines: {node: '>=10'} + + is-git-repository@2.0.0: + resolution: {integrity: sha512-HDO50CG5suIAcmqG4F1buqVXEZRPn+RaXIn9pFKq/947FBo2bCRwK7ZluEVZOy99a4IQyqsjbKEpAiOXCccOHQ==} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-interactive@1.0.0: + resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} + engines: {node: '>=8'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-path-cwd@2.2.0: + resolution: {integrity: sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==} + engines: {node: '>=6'} + + is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + + is-relative@1.0.0: + resolution: {integrity: sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==} + engines: {node: '>=0.10.0'} + + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + + is-unc-path@1.0.0: + resolution: {integrity: sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==} + engines: {node: '>=0.10.0'} + + is-unicode-supported@0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + + is-windows@1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + + is-wsl@1.1.0: + resolution: {integrity: sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==} + engines: {node: '>=4'} + + is-wsl@2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + + istanbul-lib-instrument@5.2.1: + resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} + engines: {node: '>=8'} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + jest-environment-node@29.7.0: + resolution: {integrity: sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-get-type@29.6.3: + resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-haste-map@29.7.0: + resolution: {integrity: sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-message-util@29.7.0: + resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-mock@29.7.0: + resolution: {integrity: sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-regex-util@29.6.3: + resolution: {integrity: sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-util@29.7.0: + resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-validate@29.7.0: + resolution: {integrity: sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-worker@29.7.0: + resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + joi@17.13.3: + resolution: {integrity: sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@3.14.2: + resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==} + hasBin: true + + js-yaml@4.1.1: + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} + hasBin: true + + jsc-safe-url@0.2.4: + resolution: {integrity: sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q==} + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + + jsonfile@6.2.0: + resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==} + + kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + + kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + + launch-editor@2.13.1: + resolution: {integrity: sha512-lPSddlAAluRKJ7/cjRFoXUFzaX7q/YKI7yPHuEvSJVqoXvFnJov1/Ud87Aa4zULIbA9Nja4mSPK8l0z/7eV2wA==} + + leven@3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + + lighthouse-logger@1.4.2: + resolution: {integrity: sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.debounce@4.0.8: + resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} + + lodash.throttle@4.1.1: + resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==} + + log-symbols@4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + + logkitty@0.7.1: + resolution: {integrity: sha512-/3ER20CTTbahrCrpYfPn7Xavv9diBROZpoXGVZDWMw4b/X4uuUwAC0ki85tgsdMRONURyIJbcOvS94QsUBYPbQ==} + hasBin: true + + loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + makeerror@1.0.12: + resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} + + marky@1.3.0: + resolution: {integrity: sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + + memoize-one@5.2.1: + resolution: {integrity: sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==} + + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + metro-babel-transformer@0.83.5: + resolution: {integrity: sha512-d9FfmgUEVejTiSb7bkQeLRGl6aeno2UpuPm3bo3rCYwxewj03ymvOn8s8vnS4fBqAPQ+cE9iQM40wh7nGXR+eA==} + engines: {node: '>=20.19.4'} + + metro-cache-key@0.83.5: + resolution: {integrity: sha512-Ycl8PBajB7bhbAI7Rt0xEyiF8oJ0RWX8EKkolV1KfCUlC++V/GStMSGpPLwnnBZXZWkCC5edBPzv1Hz1Yi0Euw==} + engines: {node: '>=20.19.4'} + + metro-cache@0.83.5: + resolution: {integrity: sha512-oH+s4U+IfZyg8J42bne2Skc90rcuESIYf86dYittcdWQtPfcaFXWpByPyTuWk3rR1Zz3Eh5HOrcVImfEhhJLng==} + engines: {node: '>=20.19.4'} + + metro-config@0.83.5: + resolution: {integrity: sha512-JQ/PAASXH7yczgV6OCUSRhZYME+NU8NYjI2RcaG5ga4QfQ3T/XdiLzpSb3awWZYlDCcQb36l4Vl7i0Zw7/Tf9w==} + engines: {node: '>=20.19.4'} + + metro-core@0.83.5: + resolution: {integrity: sha512-YcVcLCrf0ed4mdLa82Qob0VxYqfhmlRxUS8+TO4gosZo/gLwSvtdeOjc/Vt0pe/lvMNrBap9LlmvZM8FIsMgJQ==} + engines: {node: '>=20.19.4'} + + metro-file-map@0.83.5: + resolution: {integrity: sha512-ZEt8s3a1cnYbn40nyCD+CsZdYSlwtFh2kFym4lo+uvfM+UMMH+r/BsrC6rbNClSrt+B7rU9T+Te/sh/NL8ZZKQ==} + engines: {node: '>=20.19.4'} + + metro-minify-terser@0.83.5: + resolution: {integrity: sha512-Toe4Md1wS1PBqbvB0cFxBzKEVyyuYTUb0sgifAZh/mSvLH84qA1NAWik9sISWatzvfWf3rOGoUoO5E3f193a3Q==} + engines: {node: '>=20.19.4'} + + metro-resolver@0.83.5: + resolution: {integrity: sha512-7p3GtzVUpbAweJeCcUJihJeOQl1bDuimO5ueo1K0BUpUtR41q5EilbQ3klt16UTPPMpA+tISWBtsrqU556mY1A==} + engines: {node: '>=20.19.4'} + + metro-runtime@0.83.5: + resolution: {integrity: sha512-f+b3ue9AWTVlZe2Xrki6TAoFtKIqw30jwfk7GQ1rDUBQaE0ZQ+NkiMEtb9uwH7uAjJ87U7Tdx1Jg1OJqUfEVlA==} + engines: {node: '>=20.19.4'} + + metro-source-map@0.83.5: + resolution: {integrity: sha512-VT9bb2KO2/4tWY9Z2yeZqTUao7CicKAOps9LUg2aQzsz+04QyuXL3qgf1cLUVRjA/D6G5u1RJAlN1w9VNHtODQ==} + engines: {node: '>=20.19.4'} + + metro-symbolicate@0.83.5: + resolution: {integrity: sha512-EMIkrjNRz/hF+p0RDdxoE60+dkaTLPN3vaaGkFmX5lvFdO6HPfHA/Ywznzkev+za0VhPQ5KSdz49/MALBRteHA==} + engines: {node: '>=20.19.4'} + hasBin: true + + metro-transform-plugins@0.83.5: + resolution: {integrity: sha512-KxYKzZL+lt3Os5H2nx7YkbkWVduLZL5kPrE/Yq+Prm/DE1VLhpfnO6HtPs8vimYFKOa58ncl60GpoX0h7Wm0Vw==} + engines: {node: '>=20.19.4'} + + metro-transform-worker@0.83.5: + resolution: {integrity: sha512-8N4pjkNXc6ytlP9oAM6MwqkvUepNSW39LKYl9NjUMpRDazBQ7oBpQDc8Sz4aI8jnH6AGhF7s1m/ayxkN1t04yA==} + engines: {node: '>=20.19.4'} + + metro@0.83.5: + resolution: {integrity: sha512-BgsXevY1MBac/3ZYv/RfNFf/4iuW9X7f4H8ZNkiH+r667HD9sVujxcmu4jvEzGCAm4/WyKdZCuyhAcyhTHOucQ==} + engines: {node: '>=20.19.4'} + hasBin: true + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-db@1.54.0: + resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mime-types@3.0.2: + resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==} + engines: {node: '>=18'} + + mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + + mime@2.6.0: + resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==} + engines: {node: '>=4.0.0'} + hasBin: true + + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + + minimatch@3.1.5: + resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} + + minimatch@9.0.9: + resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==} + engines: {node: '>=16 || 14 >=14.17'} + + minipass@7.1.3: + resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} + engines: {node: '>=16 || 14 >=14.17'} + + mkdirp@1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + + ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + + negotiator@0.6.4: + resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} + engines: {node: '>= 0.6'} + + negotiator@1.0.0: + resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} + engines: {node: '>= 0.6'} + + nocache@3.0.4: + resolution: {integrity: sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw==} + engines: {node: '>=12.0.0'} + + node-int64@0.4.0: + resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} + + node-releases@2.0.36: + resolution: {integrity: sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==} + + node-stream-zip@1.15.0: + resolution: {integrity: sha512-LN4fydt9TqhZhThkZIVQnF9cwjU3qmUH9h78Mx/K7d3VvfRqqwthLwJEUOEL0QPZ0XQmNN7be5Ggit5+4dq3Bw==} + engines: {node: '>=0.12.0'} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + + nullthrows@1.1.1: + resolution: {integrity: sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==} + + ob1@0.83.5: + resolution: {integrity: sha512-vNKPYC8L5ycVANANpF/S+WZHpfnRWKx/F3AYP4QMn6ZJTh+l2HOrId0clNkEmua58NB9vmI9Qh7YOoV/4folYg==} + engines: {node: '>=20.19.4'} + + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + + on-finished@2.3.0: + resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==} + engines: {node: '>= 0.8'} + + on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + + on-headers@1.1.0: + resolution: {integrity: sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==} + engines: {node: '>= 0.8'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + + open@6.4.0: + resolution: {integrity: sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg==} + engines: {node: '>=8'} + + open@7.4.2: + resolution: {integrity: sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==} + engines: {node: '>=8'} + + ora@5.4.1: + resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} + engines: {node: '>=10'} + + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + p-map@4.0.0: + resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} + engines: {node: '>=10'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + pirates@4.0.7: + resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} + engines: {node: '>= 6'} + + pretty-format@29.7.0: + resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + promise@8.3.0: + resolution: {integrity: sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==} + + prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + + pump@3.0.4: + resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} + + qs@6.14.2: + resolution: {integrity: sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==} + engines: {node: '>=0.6'} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + queue@6.0.2: + resolution: {integrity: sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==} + + range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + + raw-body@2.5.3: + resolution: {integrity: sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==} + engines: {node: '>= 0.8'} + + react-devtools-core@6.1.5: + resolution: {integrity: sha512-ePrwPfxAnB+7hgnEr8vpKxL9cmnp7F322t8oqcPshbIQQhDKgFDW4tjhF2wjVbdXF9O/nyuy3sQWd9JGpiLPvA==} + + react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + + react-native-builder-bob@0.40.18: + resolution: {integrity: sha512-vGd6l/iaMirnVucQlm2OJWTDQjxbYxHNmqXtDRWXMRubwotKKycx1ARj/aJYbzbCdzHBB00bGzYEhUcq4sbGog==} + engines: {node: ^20.19.0 || ^22.12.0 || >= 23.4.0} + hasBin: true + + react-native-is-edge-to-edge@1.2.1: + resolution: {integrity: sha512-FLbPWl/MyYQWz+KwqOZsSyj2JmLKglHatd3xLZWskXOpRaio4LfEDEz8E/A6uD8QoTHW6Aobw1jbEwK7KMgR7Q==} + peerDependencies: + react: '*' + react-native: '*' + + react-native-monorepo-config@0.3.3: + resolution: {integrity: sha512-d1kjHRVsbd/yVkFb5rYxWYiWVzCqJgUzcc499ejfc8jH6q6XYB4U+dNpX/HsxdXZLpzEhmKvgq0PsjRAIdAVeA==} + + react-native-reanimated@4.2.2: + resolution: {integrity: sha512-o3kKvdD8cVlg12Z4u3jv0MFAt53QV4k7gD9OLwQqU8eZLyd8QvaOjVZIghMZhC2pjP93uUU44PlO5JgF8S4Vxw==} + peerDependencies: + react: '*' + react-native: '*' + react-native-worklets: '>=0.7.0' + + react-native-safe-area-context@5.7.0: + resolution: {integrity: sha512-/9/MtQz8ODphjsLdZ+GZAIcC/RtoqW9EeShf7Uvnfgm/pzYrJ75y3PV/J1wuAV1T5Dye5ygq4EAW20RoBq0ABQ==} + peerDependencies: + react: '*' + react-native: '*' + + react-native-worklets@0.7.4: + resolution: {integrity: sha512-NYOdM1MwBb3n+AtMqy1tFy3Mn8DliQtd8sbzAVRf9Gc+uvQ0zRfxN7dS8ZzoyX7t6cyQL5THuGhlnX+iFlQTag==} + peerDependencies: + '@babel/core': '*' + react: '*' + react-native: '*' + + react-native@0.83.0: + resolution: {integrity: sha512-a8wPjGfkktb1+Mjvzkky3d0u6j6zdWAzftZ2LdQtgRgqkMMfgQxD9S+ri3RNlfAFQpuCAOYUIyrNHiVkUQChxA==} + engines: {node: '>= 20.19.4'} + hasBin: true + peerDependencies: + '@types/react': ^19.1.1 + react: ^19.2.0 + peerDependenciesMeta: + '@types/react': + optional: true + + react-refresh@0.14.2: + resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} + engines: {node: '>=0.10.0'} + + react@19.2.0: + resolution: {integrity: sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==} + engines: {node: '>=0.10.0'} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + regenerate-unicode-properties@10.2.2: + resolution: {integrity: sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==} + engines: {node: '>=4'} + + regenerate@1.4.2: + resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} + + regenerator-runtime@0.13.11: + resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} + + regexpu-core@6.4.0: + resolution: {integrity: sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==} + engines: {node: '>=4'} + + regjsgen@0.8.0: + resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==} + + regjsparser@0.13.0: + resolution: {integrity: sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q==} + hasBin: true + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + require-main-filename@2.0.0: + resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + resolve@1.22.11: + resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} + engines: {node: '>= 0.4'} + hasBin: true + + restore-cursor@3.1.0: + resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} + engines: {node: '>=8'} + + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported + hasBin: true + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + scheduler@0.27.0: + resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.7.3: + resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} + engines: {node: '>=10'} + hasBin: true + + semver@7.7.4: + resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} + engines: {node: '>=10'} + hasBin: true + + send@0.19.2: + resolution: {integrity: sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==} + engines: {node: '>= 0.8.0'} + + serialize-error@2.1.0: + resolution: {integrity: sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw==} + engines: {node: '>=0.10.0'} + + serve-static@1.16.3: + resolution: {integrity: sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==} + engines: {node: '>= 0.8.0'} + + set-blocking@2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + shell-quote@1.8.3: + resolution: {integrity: sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==} + engines: {node: '>= 0.4'} + + side-channel-list@1.0.0: + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} + + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + slice-ansi@2.1.0: + resolution: {integrity: sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==} + engines: {node: '>=6'} + + source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + + source-map@0.5.7: + resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} + engines: {node: '>=0.10.0'} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + + stack-utils@2.0.6: + resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} + engines: {node: '>=10'} + + stackframe@1.3.4: + resolution: {integrity: sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==} + + stacktrace-parser@0.1.11: + resolution: {integrity: sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg==} + engines: {node: '>=6'} + + statuses@1.5.0: + resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} + engines: {node: '>= 0.6'} + + statuses@2.0.2: + resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} + engines: {node: '>= 0.8'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-ansi@5.2.0: + resolution: {integrity: sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==} + engines: {node: '>=6'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.2.0: + resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} + engines: {node: '>=12'} + + strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + + strnum@1.1.2: + resolution: {integrity: sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + terser@5.46.0: + resolution: {integrity: sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==} + engines: {node: '>=10'} + hasBin: true + + test-exclude@6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + + throat@5.0.0: + resolution: {integrity: sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==} + + tmpl@1.0.5: + resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + type-detect@4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + + type-fest@0.7.1: + resolution: {integrity: sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==} + engines: {node: '>=8'} + + type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + + unc-path-regex@0.1.2: + resolution: {integrity: sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==} + engines: {node: '>=0.10.0'} + + undici-types@7.18.2: + resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} + + unicode-canonical-property-names-ecmascript@2.0.1: + resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==} + engines: {node: '>=4'} + + unicode-match-property-ecmascript@2.0.0: + resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} + engines: {node: '>=4'} + + unicode-match-property-value-ecmascript@2.2.1: + resolution: {integrity: sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==} + engines: {node: '>=4'} + + unicode-property-aliases-ecmascript@2.2.0: + resolution: {integrity: sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==} + engines: {node: '>=4'} + + universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + + update-browserslist-db@1.2.3: + resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + + vlq@1.0.1: + resolution: {integrity: sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==} + + walker@1.0.8: + resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} + + wcwidth@1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + + whatwg-fetch@3.6.20: + resolution: {integrity: sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==} + + which-module@2.0.1: + resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + write-file-atomic@4.0.2: + resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + ws@6.2.3: + resolution: {integrity: sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + ws@7.5.10: + resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + y18n@4.0.3: + resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yaml@2.8.2: + resolution: {integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==} + engines: {node: '>= 14.6'} + hasBin: true + + yargs-parser@18.1.3: + resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} + engines: {node: '>=6'} + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@15.4.1: + resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} + engines: {node: '>=8'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + +snapshots: + + '@ark/schema@0.56.0': + dependencies: + '@ark/util': 0.56.0 + + '@ark/util@0.56.0': {} + + '@babel/code-frame@7.29.0': + dependencies: + '@babel/helper-validator-identifier': 7.28.5 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.29.0': {} + + '@babel/core@7.29.0': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) + '@babel/helpers': 7.28.6 + '@babel/parser': 7.29.0 + '@babel/template': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.29.1': + dependencies: + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + + '@babel/helper-annotate-as-pure@7.27.3': + dependencies: + '@babel/types': 7.29.0 + + '@babel/helper-compilation-targets@7.28.6': + dependencies: + '@babel/compat-data': 7.29.0 + '@babel/helper-validator-option': 7.27.1 + browserslist: 4.28.1 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-create-class-features-plugin@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-member-expression-to-functions': 7.28.5 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0) + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/traverse': 7.29.0 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-create-regexp-features-plugin@7.28.5(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-annotate-as-pure': 7.27.3 + regexpu-core: 6.4.0 + semver: 6.3.1 + + '@babel/helper-define-polyfill-provider@0.6.7(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + debug: 4.4.3 + lodash.debounce: 4.0.8 + resolve: 1.22.11 + transitivePeerDependencies: + - supports-color + + '@babel/helper-globals@7.28.0': {} + + '@babel/helper-member-expression-to-functions@7.28.5': + dependencies: + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-imports@7.28.6': + dependencies: + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-module-imports': 7.28.6 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-optimise-call-expression@7.27.1': + dependencies: + '@babel/types': 7.29.0 + + '@babel/helper-plugin-utils@7.28.6': {} + + '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-wrap-function': 7.28.6 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-replace-supers@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-member-expression-to-functions': 7.28.5 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-skip-transparent-expression-wrappers@7.27.1': + dependencies: + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-string-parser@7.27.1': {} + + '@babel/helper-validator-identifier@7.28.5': {} + + '@babel/helper-validator-option@7.27.1': {} + + '@babel/helper-wrap-function@7.28.6': + dependencies: + '@babel/template': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helpers@7.28.6': + dependencies: + '@babel/template': 7.28.6 + '@babel/types': 7.29.0 + + '@babel/parser@7.29.0': + dependencies: + '@babel/types': 7.29.0 + + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-proposal-export-default-from@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-export-default-from@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-flow@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-import-assertions@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-import-attributes@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-typescript@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-async-generator-functions@7.29.0(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.29.0) + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-async-to-generator@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-module-imports': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-block-scoped-functions@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-block-scoping@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-class-properties@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-class-properties@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-class-static-block@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-classes@7.28.4(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-globals': 7.28.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0) + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-classes@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-globals': 7.28.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0) + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-computed-properties@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/template': 7.28.6 + + '@babel/plugin-transform-destructuring@7.28.5(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-dotall-regex@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-duplicate-keys@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.29.0(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-dynamic-import@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-explicit-resource-management@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-exponentiation-operator@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-export-namespace-from@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-flow-strip-types@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-syntax-flow': 7.28.6(@babel/core@7.29.0) + + '@babel/plugin-transform-for-of@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-function-name@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-json-strings@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-literals@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-logical-assignment-operators@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-member-expression-literals@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-modules-amd@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-modules-commonjs@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-modules-systemjs@7.29.0(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-modules-umd@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-named-capturing-groups-regex@7.29.0(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-new-target@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-nullish-coalescing-operator@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-nullish-coalescing-operator@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-numeric-separator@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-object-rest-spread@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0) + '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.29.0) + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-object-super@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-optional-catch-binding@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-optional-chaining@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-optional-chaining@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-parameters@7.27.7(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-private-methods@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-private-property-in-object@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-property-literals@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-react-display-name@7.28.0(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-react-jsx-development@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/plugin-transform-react-jsx': 7.28.6(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-react-jsx@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-module-imports': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) + '@babel/types': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-react-pure-annotations@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-regenerator@7.29.0(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-regexp-modifiers@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-reserved-words@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-runtime@7.29.0(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-module-imports': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + babel-plugin-polyfill-corejs2: 0.4.16(@babel/core@7.29.0) + babel-plugin-polyfill-corejs3: 0.13.0(@babel/core@7.29.0) + babel-plugin-polyfill-regenerator: 0.6.7(@babel/core@7.29.0) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-spread@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-strict-mode@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-template-literals@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-typeof-symbol@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-typescript@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-unicode-escapes@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-unicode-property-regex@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-unicode-sets-regex@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/preset-env@7.29.0(@babel/core@7.29.0)': + dependencies: + '@babel/compat-data': 7.29.0 + '@babel/core': 7.29.0 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-validator-option': 7.27.1 + '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.28.5(@babel/core@7.29.0) + '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.29.0) + '@babel/plugin-syntax-import-assertions': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-syntax-import-attributes': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.29.0) + '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-async-generator-functions': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-async-to-generator': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-block-scoped-functions': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-block-scoping': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-class-properties': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-class-static-block': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-classes': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-computed-properties': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0) + '@babel/plugin-transform-dotall-regex': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-duplicate-keys': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-dynamic-import': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-explicit-resource-management': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-exponentiation-operator': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-json-strings': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-logical-assignment-operators': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-member-expression-literals': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-modules-amd': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-modules-systemjs': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-modules-umd': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-named-capturing-groups-regex': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-new-target': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-nullish-coalescing-operator': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-numeric-separator': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-object-rest-spread': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-object-super': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-optional-catch-binding': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.29.0) + '@babel/plugin-transform-private-methods': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-private-property-in-object': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-property-literals': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-regenerator': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-regexp-modifiers': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-reserved-words': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-spread': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-template-literals': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-typeof-symbol': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-unicode-escapes': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-unicode-property-regex': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-unicode-sets-regex': 7.28.6(@babel/core@7.29.0) + '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.29.0) + babel-plugin-polyfill-corejs2: 0.4.16(@babel/core@7.29.0) + babel-plugin-polyfill-corejs3: 0.14.1(@babel/core@7.29.0) + babel-plugin-polyfill-regenerator: 0.6.7(@babel/core@7.29.0) + core-js-compat: 3.48.0 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/types': 7.29.0 + esutils: 2.0.3 + + '@babel/preset-react@7.28.5(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-validator-option': 7.27.1 + '@babel/plugin-transform-react-display-name': 7.28.0(@babel/core@7.29.0) + '@babel/plugin-transform-react-jsx': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-react-jsx-development': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-react-pure-annotations': 7.27.1(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + '@babel/preset-typescript@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-validator-option': 7.27.1 + '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + '@babel/preset-typescript@7.28.5(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-validator-option': 7.27.1 + '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + '@babel/runtime@7.28.6': {} + + '@babel/template@7.28.6': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 + + '@babel/traverse@7.29.0': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/helper-globals': 7.28.0 + '@babel/parser': 7.29.0 + '@babel/template': 7.28.6 + '@babel/types': 7.29.0 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.29.0': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + + '@hapi/hoek@9.3.0': {} + + '@hapi/topo@5.1.0': + dependencies: + '@hapi/hoek': 9.3.0 + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.2.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@isaacs/ttlcache@1.4.1': {} + + '@istanbuljs/load-nyc-config@1.1.0': + dependencies: + camelcase: 5.3.1 + find-up: 4.1.0 + get-package-type: 0.1.0 + js-yaml: 3.14.2 + resolve-from: 5.0.0 + + '@istanbuljs/schema@0.1.3': {} + + '@jest/create-cache-key-function@29.7.0': + dependencies: + '@jest/types': 29.6.3 + + '@jest/environment@29.7.0': + dependencies: + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 25.5.0 + jest-mock: 29.7.0 + + '@jest/fake-timers@29.7.0': + dependencies: + '@jest/types': 29.6.3 + '@sinonjs/fake-timers': 10.3.0 + '@types/node': 25.5.0 + jest-message-util: 29.7.0 + jest-mock: 29.7.0 + jest-util: 29.7.0 + + '@jest/schemas@29.6.3': + dependencies: + '@sinclair/typebox': 0.27.10 + + '@jest/transform@29.7.0': + dependencies: + '@babel/core': 7.29.0 + '@jest/types': 29.6.3 + '@jridgewell/trace-mapping': 0.3.31 + babel-plugin-istanbul: 6.1.1 + chalk: 4.1.2 + convert-source-map: 2.0.0 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-regex-util: 29.6.3 + jest-util: 29.7.0 + micromatch: 4.0.8 + pirates: 4.0.7 + slash: 3.0.0 + write-file-atomic: 4.0.2 + transitivePeerDependencies: + - supports-color + + '@jest/types@29.6.3': + dependencies: + '@jest/schemas': 29.6.3 + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 25.5.0 + '@types/yargs': 17.0.35 + chalk: 4.1.2 + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/source-map@0.3.11': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.20.1 + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@react-native-community/cli-clean@20.0.0': + dependencies: + '@react-native-community/cli-tools': 20.0.0 + chalk: 4.1.2 + execa: 5.1.1 + fast-glob: 3.3.3 + + '@react-native-community/cli-config-android@20.0.0': + dependencies: + '@react-native-community/cli-tools': 20.0.0 + chalk: 4.1.2 + fast-glob: 3.3.3 + fast-xml-parser: 4.5.4 + + '@react-native-community/cli-config-apple@20.0.0': + dependencies: + '@react-native-community/cli-tools': 20.0.0 + chalk: 4.1.2 + execa: 5.1.1 + fast-glob: 3.3.3 + + '@react-native-community/cli-config@20.0.0': + dependencies: + '@react-native-community/cli-tools': 20.0.0 + chalk: 4.1.2 + cosmiconfig: 9.0.1 + deepmerge: 4.3.1 + fast-glob: 3.3.3 + joi: 17.13.3 + transitivePeerDependencies: + - typescript + + '@react-native-community/cli-doctor@20.0.0': + dependencies: + '@react-native-community/cli-config': 20.0.0 + '@react-native-community/cli-platform-android': 20.0.0 + '@react-native-community/cli-platform-apple': 20.0.0 + '@react-native-community/cli-platform-ios': 20.0.0 + '@react-native-community/cli-tools': 20.0.0 + chalk: 4.1.2 + command-exists: 1.2.9 + deepmerge: 4.3.1 + envinfo: 7.21.0 + execa: 5.1.1 + node-stream-zip: 1.15.0 + ora: 5.4.1 + semver: 7.7.4 + wcwidth: 1.0.1 + yaml: 2.8.2 + transitivePeerDependencies: + - typescript + + '@react-native-community/cli-platform-android@20.0.0': + dependencies: + '@react-native-community/cli-config-android': 20.0.0 + '@react-native-community/cli-tools': 20.0.0 + chalk: 4.1.2 + execa: 5.1.1 + logkitty: 0.7.1 + + '@react-native-community/cli-platform-apple@20.0.0': + dependencies: + '@react-native-community/cli-config-apple': 20.0.0 + '@react-native-community/cli-tools': 20.0.0 + chalk: 4.1.2 + execa: 5.1.1 + fast-xml-parser: 4.5.4 + + '@react-native-community/cli-platform-ios@20.0.0': + dependencies: + '@react-native-community/cli-platform-apple': 20.0.0 + + '@react-native-community/cli-server-api@20.0.0': + dependencies: + '@react-native-community/cli-tools': 20.0.0 + body-parser: 1.20.4 + compression: 1.8.1 + connect: 3.7.0 + errorhandler: 1.5.2 + nocache: 3.0.4 + open: 6.4.0 + pretty-format: 29.7.0 + serve-static: 1.16.3 + ws: 6.2.3 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + '@react-native-community/cli-tools@20.0.0': + dependencies: + '@vscode/sudo-prompt': 9.3.2 + appdirsjs: 1.2.7 + chalk: 4.1.2 + execa: 5.1.1 + find-up: 5.0.0 + launch-editor: 2.13.1 + mime: 2.6.0 + ora: 5.4.1 + prompts: 2.4.2 + semver: 7.7.4 + + '@react-native-community/cli-types@20.0.0': + dependencies: + joi: 17.13.3 + + '@react-native-community/cli@20.0.0': + dependencies: + '@react-native-community/cli-clean': 20.0.0 + '@react-native-community/cli-config': 20.0.0 + '@react-native-community/cli-doctor': 20.0.0 + '@react-native-community/cli-server-api': 20.0.0 + '@react-native-community/cli-tools': 20.0.0 + '@react-native-community/cli-types': 20.0.0 + chalk: 4.1.2 + commander: 9.5.0 + deepmerge: 4.3.1 + execa: 5.1.1 + find-up: 5.0.0 + fs-extra: 8.1.0 + graceful-fs: 4.2.11 + prompts: 2.4.2 + semver: 7.7.4 + transitivePeerDependencies: + - bufferutil + - supports-color + - typescript + - utf-8-validate + + '@react-native/assets-registry@0.83.0': {} + + '@react-native/babel-plugin-codegen@0.83.0(@babel/core@7.29.0)': + dependencies: + '@babel/traverse': 7.29.0 + '@react-native/codegen': 0.83.0(@babel/core@7.29.0) + transitivePeerDependencies: + - '@babel/core' + - supports-color + + '@react-native/babel-preset@0.83.0(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/plugin-proposal-export-default-from': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-export-default-from': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-async-generator-functions': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-async-to-generator': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-block-scoping': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-class-properties': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-classes': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-computed-properties': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0) + '@babel/plugin-transform-flow-strip-types': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-logical-assignment-operators': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-named-capturing-groups-regex': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-nullish-coalescing-operator': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-numeric-separator': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-object-rest-spread': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-optional-catch-binding': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.29.0) + '@babel/plugin-transform-private-methods': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-private-property-in-object': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-react-display-name': 7.28.0(@babel/core@7.29.0) + '@babel/plugin-transform-react-jsx': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-regenerator': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-runtime': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-spread': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.29.0) + '@babel/template': 7.28.6 + '@react-native/babel-plugin-codegen': 0.83.0(@babel/core@7.29.0) + babel-plugin-syntax-hermes-parser: 0.32.0 + babel-plugin-transform-flow-enums: 0.0.2(@babel/core@7.29.0) + react-refresh: 0.14.2 + transitivePeerDependencies: + - supports-color + + '@react-native/codegen@0.83.0(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/parser': 7.29.0 + glob: 7.2.3 + hermes-parser: 0.32.0 + invariant: 2.2.4 + nullthrows: 1.1.1 + yargs: 17.7.2 + + '@react-native/community-cli-plugin@0.83.0(@react-native-community/cli@20.0.0)(@react-native/metro-config@0.83.0(@babel/core@7.29.0))': + dependencies: + '@react-native/dev-middleware': 0.83.0 + debug: 4.4.3 + invariant: 2.2.4 + metro: 0.83.5 + metro-config: 0.83.5 + metro-core: 0.83.5 + semver: 7.7.4 + optionalDependencies: + '@react-native-community/cli': 20.0.0 + '@react-native/metro-config': 0.83.0(@babel/core@7.29.0) + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + '@react-native/debugger-frontend@0.83.0': {} + + '@react-native/debugger-shell@0.83.0': + dependencies: + cross-spawn: 7.0.6 + fb-dotslash: 0.5.8 + + '@react-native/dev-middleware@0.83.0': + dependencies: + '@isaacs/ttlcache': 1.4.1 + '@react-native/debugger-frontend': 0.83.0 + '@react-native/debugger-shell': 0.83.0 + chrome-launcher: 0.15.2 + chromium-edge-launcher: 0.2.0 + connect: 3.7.0 + debug: 4.4.3 + invariant: 2.2.4 + nullthrows: 1.1.1 + open: 7.4.2 + serve-static: 1.16.3 + ws: 7.5.10 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + '@react-native/gradle-plugin@0.83.0': {} + + '@react-native/js-polyfills@0.83.0': {} + + '@react-native/metro-babel-transformer@0.83.0(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@react-native/babel-preset': 0.83.0(@babel/core@7.29.0) + hermes-parser: 0.32.0 + nullthrows: 1.1.1 + transitivePeerDependencies: + - supports-color + + '@react-native/metro-config@0.83.0(@babel/core@7.29.0)': + dependencies: + '@react-native/js-polyfills': 0.83.0 + '@react-native/metro-babel-transformer': 0.83.0(@babel/core@7.29.0) + metro-config: 0.83.5 + metro-runtime: 0.83.5 + transitivePeerDependencies: + - '@babel/core' + - bufferutil + - supports-color + - utf-8-validate + + '@react-native/normalize-colors@0.83.0': {} + + '@react-native/typescript-config@0.83.0': {} + + '@react-native/virtualized-lists@0.83.0(@types/react@19.2.14)(react-native@0.83.0(@babel/core@7.29.0)(@react-native-community/cli@20.0.0)(@react-native/metro-config@0.83.0(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.0))(react@19.2.0)': + dependencies: + invariant: 2.2.4 + nullthrows: 1.1.1 + react: 19.2.0 + react-native: 0.83.0(@babel/core@7.29.0)(@react-native-community/cli@20.0.0)(@react-native/metro-config@0.83.0(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.0) + optionalDependencies: + '@types/react': 19.2.14 + + '@sideway/address@4.1.5': + dependencies: + '@hapi/hoek': 9.3.0 + + '@sideway/formula@3.0.1': {} + + '@sideway/pinpoint@2.0.0': {} + + '@sinclair/typebox@0.27.10': {} + + '@sinonjs/commons@3.0.1': + dependencies: + type-detect: 4.0.8 + + '@sinonjs/fake-timers@10.3.0': + dependencies: + '@sinonjs/commons': 3.0.1 + + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 + '@types/babel__generator': 7.27.0 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.28.0 + + '@types/babel__generator@7.27.0': + dependencies: + '@babel/types': 7.29.0 + + '@types/babel__template@7.4.4': + dependencies: + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 + + '@types/babel__traverse@7.28.0': + dependencies: + '@babel/types': 7.29.0 + + '@types/graceful-fs@4.1.9': + dependencies: + '@types/node': 25.5.0 + + '@types/istanbul-lib-coverage@2.0.6': {} + + '@types/istanbul-lib-report@3.0.3': + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + + '@types/istanbul-reports@3.0.4': + dependencies: + '@types/istanbul-lib-report': 3.0.3 + + '@types/node@25.5.0': + dependencies: + undici-types: 7.18.2 + + '@types/react@19.2.14': + dependencies: + csstype: 3.2.3 + + '@types/stack-utils@2.0.3': {} + + '@types/yargs-parser@21.0.3': {} + + '@types/yargs@17.0.35': + dependencies: + '@types/yargs-parser': 21.0.3 + + '@vscode/sudo-prompt@9.3.2': {} + + abort-controller@3.0.0: + dependencies: + event-target-shim: 5.0.1 + + accepts@1.3.8: + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + + accepts@2.0.0: + dependencies: + mime-types: 3.0.2 + negotiator: 1.0.0 + + acorn@8.16.0: {} + + agent-base@7.1.4: {} + + aggregate-error@3.1.0: + dependencies: + clean-stack: 2.2.0 + indent-string: 4.0.0 + + anser@1.4.10: {} + + ansi-fragments@0.2.1: + dependencies: + colorette: 1.4.0 + slice-ansi: 2.1.0 + strip-ansi: 5.2.0 + + ansi-regex@4.1.1: {} + + ansi-regex@5.0.1: {} + + ansi-regex@6.2.2: {} + + ansi-styles@3.2.1: + dependencies: + color-convert: 1.9.3 + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@5.2.0: {} + + ansi-styles@6.2.3: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + appdirsjs@1.2.7: {} + + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + + argparse@2.0.1: {} + + arkregex@0.0.5: + dependencies: + '@ark/util': 0.56.0 + + arktype@2.2.0: + dependencies: + '@ark/schema': 0.56.0 + '@ark/util': 0.56.0 + arkregex: 0.0.5 + + array-union@2.1.0: {} + + asap@2.0.6: {} + + astral-regex@1.0.0: {} + + async-limiter@1.0.1: {} + + babel-jest@29.7.0(@babel/core@7.29.0): + dependencies: + '@babel/core': 7.29.0 + '@jest/transform': 29.7.0 + '@types/babel__core': 7.20.5 + babel-plugin-istanbul: 6.1.1 + babel-preset-jest: 29.6.3(@babel/core@7.29.0) + chalk: 4.1.2 + graceful-fs: 4.2.11 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-istanbul@6.1.1: + dependencies: + '@babel/helper-plugin-utils': 7.28.6 + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-instrument: 5.2.1 + test-exclude: 6.0.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-jest-hoist@29.6.3: + dependencies: + '@babel/template': 7.28.6 + '@babel/types': 7.29.0 + '@types/babel__core': 7.20.5 + '@types/babel__traverse': 7.28.0 + + babel-plugin-polyfill-corejs2@0.4.16(@babel/core@7.29.0): + dependencies: + '@babel/compat-data': 7.29.0 + '@babel/core': 7.29.0 + '@babel/helper-define-polyfill-provider': 0.6.7(@babel/core@7.29.0) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + babel-plugin-polyfill-corejs3@0.13.0(@babel/core@7.29.0): + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-define-polyfill-provider': 0.6.7(@babel/core@7.29.0) + core-js-compat: 3.48.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-polyfill-corejs3@0.14.1(@babel/core@7.29.0): + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-define-polyfill-provider': 0.6.7(@babel/core@7.29.0) + core-js-compat: 3.48.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-polyfill-regenerator@0.6.7(@babel/core@7.29.0): + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-define-polyfill-provider': 0.6.7(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + babel-plugin-syntax-hermes-parser@0.28.1: + dependencies: + hermes-parser: 0.28.1 + + babel-plugin-syntax-hermes-parser@0.32.0: + dependencies: + hermes-parser: 0.32.0 + + babel-plugin-transform-flow-enums@0.0.2(@babel/core@7.29.0): + dependencies: + '@babel/plugin-syntax-flow': 7.28.6(@babel/core@7.29.0) + transitivePeerDependencies: + - '@babel/core' + + babel-preset-current-node-syntax@1.2.0(@babel/core@7.29.0): + dependencies: + '@babel/core': 7.29.0 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.29.0) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.29.0) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.29.0) + '@babel/plugin-syntax-import-attributes': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.29.0) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.29.0) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.29.0) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.29.0) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.29.0) + + babel-preset-jest@29.6.3(@babel/core@7.29.0): + dependencies: + '@babel/core': 7.29.0 + babel-plugin-jest-hoist: 29.6.3 + babel-preset-current-node-syntax: 1.2.0(@babel/core@7.29.0) + + balanced-match@1.0.2: {} + + base64-js@1.5.1: {} + + baseline-browser-mapping@2.10.8: {} + + bl@4.1.0: + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + + body-parser@1.20.4: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.1 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.14.2 + raw-body: 2.5.3 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + brace-expansion@1.1.12: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.2: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browserslist@4.28.1: + dependencies: + baseline-browser-mapping: 2.10.8 + caniuse-lite: 1.0.30001779 + electron-to-chromium: 1.5.313 + node-releases: 2.0.36 + update-browserslist-db: 1.2.3(browserslist@4.28.1) + + bser@2.1.1: + dependencies: + node-int64: 0.4.0 + + buffer-from@1.1.2: {} + + buffer@5.7.1: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + bytes@3.1.2: {} + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + callsites@3.1.0: {} + + camelcase@5.3.1: {} + + camelcase@6.3.0: {} + + caniuse-lite@1.0.30001779: {} + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chrome-launcher@0.15.2: + dependencies: + '@types/node': 25.5.0 + escape-string-regexp: 4.0.0 + is-wsl: 2.2.0 + lighthouse-logger: 1.4.2 + transitivePeerDependencies: + - supports-color + + chromium-edge-launcher@0.2.0: + dependencies: + '@types/node': 25.5.0 + escape-string-regexp: 4.0.0 + is-wsl: 2.2.0 + lighthouse-logger: 1.4.2 + mkdirp: 1.0.4 + rimraf: 3.0.2 + transitivePeerDependencies: + - supports-color + + ci-info@2.0.0: {} + + ci-info@3.9.0: {} + + clean-stack@2.2.0: {} + + cli-cursor@3.1.0: + dependencies: + restore-cursor: 3.1.0 + + cli-spinners@2.9.2: {} + + cliui@6.0.0: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + clone@1.0.4: {} + + color-convert@1.9.3: + dependencies: + color-name: 1.1.3 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.3: {} + + color-name@1.1.4: {} + + colorette@1.4.0: {} + + command-exists@1.2.9: {} + + commander@12.1.0: {} + + commander@2.20.3: {} + + commander@9.5.0: {} + + compressible@2.0.18: + dependencies: + mime-db: 1.54.0 + + compression@1.8.1: + dependencies: + bytes: 3.1.2 + compressible: 2.0.18 + debug: 2.6.9 + negotiator: 0.6.4 + on-headers: 1.1.0 + safe-buffer: 5.2.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + concat-map@0.0.1: {} + + connect@3.7.0: + dependencies: + debug: 2.6.9 + finalhandler: 1.1.2 + parseurl: 1.3.3 + utils-merge: 1.0.1 + transitivePeerDependencies: + - supports-color + + content-type@1.0.5: {} + + convert-source-map@2.0.0: {} + + core-js-compat@3.48.0: + dependencies: + browserslist: 4.28.1 + + cosmiconfig@9.0.1: + dependencies: + env-paths: 2.2.1 + import-fresh: 3.3.1 + js-yaml: 4.1.1 + parse-json: 5.2.0 + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + csstype@3.2.3: {} + + dayjs@1.11.20: {} + + debug@2.6.9: + dependencies: + ms: 2.0.0 + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + decamelize@1.2.0: {} + + dedent@0.7.0: {} + + deepmerge@4.3.1: {} + + defaults@1.0.4: + dependencies: + clone: 1.0.4 + + del@6.1.1: + dependencies: + globby: 11.1.0 + graceful-fs: 4.2.11 + is-glob: 4.0.3 + is-path-cwd: 2.2.0 + is-path-inside: 3.0.3 + p-map: 4.0.0 + rimraf: 3.0.2 + slash: 3.0.0 + + depd@2.0.0: {} + + destroy@1.2.0: {} + + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + eastasianwidth@0.2.0: {} + + ee-first@1.1.1: {} + + electron-to-chromium@1.5.313: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + encodeurl@1.0.2: {} + + encodeurl@2.0.0: {} + + end-of-stream@1.4.5: + dependencies: + once: 1.4.0 + + env-paths@2.2.1: {} + + envinfo@7.21.0: {} + + error-ex@1.3.4: + dependencies: + is-arrayish: 0.2.1 + + error-stack-parser@2.1.4: + dependencies: + stackframe: 1.3.4 + + errorhandler@1.5.2: + dependencies: + accepts: 1.3.8 + escape-html: 1.0.3 + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + escalade@3.2.0: {} + + escape-html@1.0.3: {} + + escape-string-regexp@2.0.0: {} + + escape-string-regexp@4.0.0: {} + + escape-string-regexp@5.0.0: {} + + esprima@4.0.1: {} + + esutils@2.0.3: {} + + etag@1.8.1: {} + + event-target-shim@5.0.1: {} + + execa@4.1.0: + dependencies: + cross-spawn: 7.0.6 + get-stream: 5.2.0 + human-signals: 1.1.1 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + + execa@5.1.1: + dependencies: + cross-spawn: 7.0.6 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + + exponential-backoff@3.1.3: {} + + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fast-json-stable-stringify@2.1.0: {} + + fast-xml-parser@4.5.4: + dependencies: + strnum: 1.1.2 + + fastq@1.20.1: + dependencies: + reusify: 1.1.0 + + fb-dotslash@0.5.8: {} + + fb-watchman@2.0.2: + dependencies: + bser: 2.1.1 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + finalhandler@1.1.2: + dependencies: + debug: 2.6.9 + encodeurl: 1.0.2 + escape-html: 1.0.3 + on-finished: 2.3.0 + parseurl: 1.3.3 + statuses: 1.5.0 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flow-enums-runtime@0.0.6: {} + + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + fresh@0.5.2: {} + + fs-extra@10.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.2.0 + universalify: 2.0.1 + + fs-extra@8.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + + fs.realpath@1.0.0: {} + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + gensync@1.0.0-beta.2: {} + + get-caller-file@2.0.5: {} + + get-intrinsic@1.3.0: + 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 + + get-package-type@0.1.0: {} + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + get-stream@5.2.0: + dependencies: + pump: 3.0.4 + + get-stream@6.0.1: {} + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob@10.5.0: + dependencies: + foreground-child: 3.3.1 + jackspeak: 3.4.3 + minimatch: 9.0.9 + minipass: 7.1.3 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.5 + once: 1.4.0 + path-is-absolute: 1.0.1 + + globby@11.1.0: + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.3 + ignore: 5.3.2 + merge2: 1.4.1 + slash: 3.0.0 + + gopd@1.2.0: {} + + graceful-fs@4.2.11: {} + + has-flag@4.0.0: {} + + has-symbols@1.1.0: {} + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + hermes-compiler@0.14.0: {} + + hermes-estree@0.28.1: {} + + hermes-estree@0.32.0: {} + + hermes-estree@0.33.3: {} + + hermes-parser@0.28.1: + dependencies: + hermes-estree: 0.28.1 + + hermes-parser@0.32.0: + dependencies: + hermes-estree: 0.32.0 + + hermes-parser@0.33.3: + dependencies: + hermes-estree: 0.33.3 + + http-errors@2.0.1: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.2 + toidentifier: 1.0.1 + + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + human-signals@1.1.1: {} + + human-signals@2.1.0: {} + + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + + ieee754@1.2.1: {} + + ignore@5.3.2: {} + + image-size@1.2.1: + dependencies: + queue: 6.0.2 + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + imurmurhash@0.1.4: {} + + indent-string@4.0.0: {} + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + inherits@2.0.4: {} + + invariant@2.2.4: + dependencies: + loose-envify: 1.4.0 + + is-absolute@1.0.0: + dependencies: + is-relative: 1.0.0 + is-windows: 1.0.2 + + is-arrayish@0.2.1: {} + + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + + is-docker@2.2.1: {} + + is-extglob@2.1.1: {} + + is-fullwidth-code-point@2.0.0: {} + + is-fullwidth-code-point@3.0.0: {} + + is-git-dirty@2.0.2: + dependencies: + execa: 4.1.0 + is-git-repository: 2.0.0 + + is-git-repository@2.0.0: + dependencies: + execa: 4.1.0 + is-absolute: 1.0.0 + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-interactive@1.0.0: {} + + is-number@7.0.0: {} + + is-path-cwd@2.2.0: {} + + is-path-inside@3.0.3: {} + + is-relative@1.0.0: + dependencies: + is-unc-path: 1.0.0 + + is-stream@2.0.1: {} + + is-unc-path@1.0.0: + dependencies: + unc-path-regex: 0.1.2 + + is-unicode-supported@0.1.0: {} + + is-windows@1.0.2: {} + + is-wsl@1.1.0: {} + + is-wsl@2.2.0: + dependencies: + is-docker: 2.2.1 + + isexe@2.0.0: {} + + istanbul-lib-coverage@3.2.2: {} + + istanbul-lib-instrument@5.2.1: + dependencies: + '@babel/core': 7.29.0 + '@babel/parser': 7.29.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.2 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + jest-environment-node@29.7.0: + dependencies: + '@jest/environment': 29.7.0 + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 25.5.0 + jest-mock: 29.7.0 + jest-util: 29.7.0 + + jest-get-type@29.6.3: {} + + jest-haste-map@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/graceful-fs': 4.1.9 + '@types/node': 25.5.0 + anymatch: 3.1.3 + fb-watchman: 2.0.2 + graceful-fs: 4.2.11 + jest-regex-util: 29.6.3 + jest-util: 29.7.0 + jest-worker: 29.7.0 + micromatch: 4.0.8 + walker: 1.0.8 + optionalDependencies: + fsevents: 2.3.3 + + jest-message-util@29.7.0: + dependencies: + '@babel/code-frame': 7.29.0 + '@jest/types': 29.6.3 + '@types/stack-utils': 2.0.3 + chalk: 4.1.2 + graceful-fs: 4.2.11 + micromatch: 4.0.8 + pretty-format: 29.7.0 + slash: 3.0.0 + stack-utils: 2.0.6 + + jest-mock@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/node': 25.5.0 + jest-util: 29.7.0 + + jest-regex-util@29.6.3: {} + + jest-util@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/node': 25.5.0 + chalk: 4.1.2 + ci-info: 3.9.0 + graceful-fs: 4.2.11 + picomatch: 2.3.1 + + jest-validate@29.7.0: + dependencies: + '@jest/types': 29.6.3 + camelcase: 6.3.0 + chalk: 4.1.2 + jest-get-type: 29.6.3 + leven: 3.1.0 + pretty-format: 29.7.0 + + jest-worker@29.7.0: + dependencies: + '@types/node': 25.5.0 + jest-util: 29.7.0 + merge-stream: 2.0.0 + supports-color: 8.1.1 + + joi@17.13.3: + dependencies: + '@hapi/hoek': 9.3.0 + '@hapi/topo': 5.1.0 + '@sideway/address': 4.1.5 + '@sideway/formula': 3.0.1 + '@sideway/pinpoint': 2.0.0 + + js-tokens@4.0.0: {} + + js-yaml@3.14.2: + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + + js-yaml@4.1.1: + dependencies: + argparse: 2.0.1 + + jsc-safe-url@0.2.4: {} + + jsesc@3.1.0: {} + + json-parse-even-better-errors@2.3.1: {} + + json5@2.2.3: {} + + jsonfile@4.0.0: + optionalDependencies: + graceful-fs: 4.2.11 + + jsonfile@6.2.0: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + + kleur@3.0.3: {} + + kleur@4.1.5: {} + + launch-editor@2.13.1: + dependencies: + picocolors: 1.1.1 + shell-quote: 1.8.3 + + leven@3.1.0: {} + + lighthouse-logger@1.4.2: + dependencies: + debug: 2.6.9 + marky: 1.3.0 + transitivePeerDependencies: + - supports-color + + lines-and-columns@1.2.4: {} + + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash.debounce@4.0.8: {} + + lodash.throttle@4.1.1: {} + + log-symbols@4.1.0: + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + + logkitty@0.7.1: + dependencies: + ansi-fragments: 0.2.1 + dayjs: 1.11.20 + yargs: 15.4.1 + + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + + lru-cache@10.4.3: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + makeerror@1.0.12: + dependencies: + tmpl: 1.0.5 + + marky@1.3.0: {} + + math-intrinsics@1.1.0: {} + + media-typer@0.3.0: {} + + memoize-one@5.2.1: {} + + merge-stream@2.0.0: {} + + merge2@1.4.1: {} + + metro-babel-transformer@0.83.5: + dependencies: + '@babel/core': 7.29.0 + flow-enums-runtime: 0.0.6 + hermes-parser: 0.33.3 + nullthrows: 1.1.1 + transitivePeerDependencies: + - supports-color + + metro-cache-key@0.83.5: + dependencies: + flow-enums-runtime: 0.0.6 + + metro-cache@0.83.5: + dependencies: + exponential-backoff: 3.1.3 + flow-enums-runtime: 0.0.6 + https-proxy-agent: 7.0.6 + metro-core: 0.83.5 + transitivePeerDependencies: + - supports-color + + metro-config@0.83.5: + dependencies: + connect: 3.7.0 + flow-enums-runtime: 0.0.6 + jest-validate: 29.7.0 + metro: 0.83.5 + metro-cache: 0.83.5 + metro-core: 0.83.5 + metro-runtime: 0.83.5 + yaml: 2.8.2 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + metro-core@0.83.5: + dependencies: + flow-enums-runtime: 0.0.6 + lodash.throttle: 4.1.1 + metro-resolver: 0.83.5 + + metro-file-map@0.83.5: + dependencies: + debug: 4.4.3 + fb-watchman: 2.0.2 + flow-enums-runtime: 0.0.6 + graceful-fs: 4.2.11 + invariant: 2.2.4 + jest-worker: 29.7.0 + micromatch: 4.0.8 + nullthrows: 1.1.1 + walker: 1.0.8 + transitivePeerDependencies: + - supports-color + + metro-minify-terser@0.83.5: + dependencies: + flow-enums-runtime: 0.0.6 + terser: 5.46.0 + + metro-resolver@0.83.5: + dependencies: + flow-enums-runtime: 0.0.6 + + metro-runtime@0.83.5: + dependencies: + '@babel/runtime': 7.28.6 + flow-enums-runtime: 0.0.6 + + metro-source-map@0.83.5: + dependencies: + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + flow-enums-runtime: 0.0.6 + invariant: 2.2.4 + metro-symbolicate: 0.83.5 + nullthrows: 1.1.1 + ob1: 0.83.5 + source-map: 0.5.7 + vlq: 1.0.1 + transitivePeerDependencies: + - supports-color + + metro-symbolicate@0.83.5: + dependencies: + flow-enums-runtime: 0.0.6 + invariant: 2.2.4 + metro-source-map: 0.83.5 + nullthrows: 1.1.1 + source-map: 0.5.7 + vlq: 1.0.1 + transitivePeerDependencies: + - supports-color + + metro-transform-plugins@0.83.5: + dependencies: + '@babel/core': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/template': 7.28.6 + '@babel/traverse': 7.29.0 + flow-enums-runtime: 0.0.6 + nullthrows: 1.1.1 + transitivePeerDependencies: + - supports-color + + metro-transform-worker@0.83.5: + dependencies: + '@babel/core': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 + flow-enums-runtime: 0.0.6 + metro: 0.83.5 + metro-babel-transformer: 0.83.5 + metro-cache: 0.83.5 + metro-cache-key: 0.83.5 + metro-minify-terser: 0.83.5 + metro-source-map: 0.83.5 + metro-transform-plugins: 0.83.5 + nullthrows: 1.1.1 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + metro@0.83.5: + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/core': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/parser': 7.29.0 + '@babel/template': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + accepts: 2.0.0 + chalk: 4.1.2 + ci-info: 2.0.0 + connect: 3.7.0 + debug: 4.4.3 + error-stack-parser: 2.1.4 + flow-enums-runtime: 0.0.6 + graceful-fs: 4.2.11 + hermes-parser: 0.33.3 + image-size: 1.2.1 + invariant: 2.2.4 + jest-worker: 29.7.0 + jsc-safe-url: 0.2.4 + lodash.throttle: 4.1.1 + metro-babel-transformer: 0.83.5 + metro-cache: 0.83.5 + metro-cache-key: 0.83.5 + metro-config: 0.83.5 + metro-core: 0.83.5 + metro-file-map: 0.83.5 + metro-resolver: 0.83.5 + metro-runtime: 0.83.5 + metro-source-map: 0.83.5 + metro-symbolicate: 0.83.5 + metro-transform-plugins: 0.83.5 + metro-transform-worker: 0.83.5 + mime-types: 3.0.2 + nullthrows: 1.1.1 + serialize-error: 2.1.0 + source-map: 0.5.7 + throat: 5.0.0 + ws: 7.5.10 + yargs: 17.7.2 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mime-db@1.52.0: {} + + mime-db@1.54.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mime-types@3.0.2: + dependencies: + mime-db: 1.54.0 + + mime@1.6.0: {} + + mime@2.6.0: {} + + mimic-fn@2.1.0: {} + + minimatch@3.1.5: + dependencies: + brace-expansion: 1.1.12 + + minimatch@9.0.9: + dependencies: + brace-expansion: 2.0.2 + + minipass@7.1.3: {} + + mkdirp@1.0.4: {} + + ms@2.0.0: {} + + ms@2.1.3: {} + + negotiator@0.6.3: {} + + negotiator@0.6.4: {} + + negotiator@1.0.0: {} + + nocache@3.0.4: {} + + node-int64@0.4.0: {} + + node-releases@2.0.36: {} + + node-stream-zip@1.15.0: {} + + normalize-path@3.0.0: {} + + npm-run-path@4.0.1: + dependencies: + path-key: 3.1.1 + + nullthrows@1.1.1: {} + + ob1@0.83.5: + dependencies: + flow-enums-runtime: 0.0.6 + + object-inspect@1.13.4: {} + + on-finished@2.3.0: + dependencies: + ee-first: 1.1.1 + + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 + + on-headers@1.1.0: {} + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 + + open@6.4.0: + dependencies: + is-wsl: 1.1.0 + + open@7.4.2: + dependencies: + is-docker: 2.2.1 + is-wsl: 2.2.0 + + ora@5.4.1: + dependencies: + bl: 4.1.0 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-spinners: 2.9.2 + is-interactive: 1.0.0 + is-unicode-supported: 0.1.0 + log-symbols: 4.1.0 + strip-ansi: 6.0.1 + wcwidth: 1.0.1 + + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + p-map@4.0.0: + dependencies: + aggregate-error: 3.1.0 + + p-try@2.2.0: {} + + package-json-from-dist@1.0.1: {} + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.29.0 + error-ex: 1.3.4 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + + parseurl@1.3.3: {} + + path-exists@4.0.0: {} + + path-is-absolute@1.0.1: {} + + path-key@3.1.1: {} + + path-parse@1.0.7: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.3 + + path-type@4.0.0: {} + + picocolors@1.1.1: {} + + picomatch@2.3.1: {} + + pirates@4.0.7: {} + + pretty-format@29.7.0: + dependencies: + '@jest/schemas': 29.6.3 + ansi-styles: 5.2.0 + react-is: 18.3.1 + + promise@8.3.0: + dependencies: + asap: 2.0.6 + + prompts@2.4.2: + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + + pump@3.0.4: + dependencies: + end-of-stream: 1.4.5 + once: 1.4.0 + + qs@6.14.2: + dependencies: + side-channel: 1.1.0 + + queue-microtask@1.2.3: {} + + queue@6.0.2: + dependencies: + inherits: 2.0.4 + + range-parser@1.2.1: {} + + raw-body@2.5.3: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.1 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + + react-devtools-core@6.1.5: + dependencies: + shell-quote: 1.8.3 + ws: 7.5.10 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + react-is@18.3.1: {} + + react-native-builder-bob@0.40.18: + dependencies: + '@babel/core': 7.29.0 + '@babel/plugin-transform-flow-strip-types': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-strict-mode': 7.27.1(@babel/core@7.29.0) + '@babel/preset-env': 7.29.0(@babel/core@7.29.0) + '@babel/preset-react': 7.28.5(@babel/core@7.29.0) + '@babel/preset-typescript': 7.28.5(@babel/core@7.29.0) + arktype: 2.2.0 + babel-plugin-syntax-hermes-parser: 0.28.1 + browserslist: 4.28.1 + cross-spawn: 7.0.6 + dedent: 0.7.0 + del: 6.1.1 + escape-string-regexp: 4.0.0 + fs-extra: 10.1.0 + glob: 10.5.0 + is-git-dirty: 2.0.2 + json5: 2.2.3 + kleur: 4.1.5 + prompts: 2.4.2 + react-native-monorepo-config: 0.3.3 + which: 2.0.2 + yargs: 17.7.2 + transitivePeerDependencies: + - supports-color + + react-native-is-edge-to-edge@1.2.1(react-native@0.83.0(@babel/core@7.29.0)(@react-native-community/cli@20.0.0)(@react-native/metro-config@0.83.0(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.0))(react@19.2.0): + dependencies: + react: 19.2.0 + react-native: 0.83.0(@babel/core@7.29.0)(@react-native-community/cli@20.0.0)(@react-native/metro-config@0.83.0(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.0) + + react-native-monorepo-config@0.3.3: + dependencies: + escape-string-regexp: 5.0.0 + fast-glob: 3.3.3 + + react-native-reanimated@4.2.2(react-native-worklets@0.7.4(@babel/core@7.29.0)(react-native@0.83.0(@babel/core@7.29.0)(@react-native-community/cli@20.0.0)(@react-native/metro-config@0.83.0(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.0))(react@19.2.0))(react-native@0.83.0(@babel/core@7.29.0)(@react-native-community/cli@20.0.0)(@react-native/metro-config@0.83.0(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.0))(react@19.2.0): + dependencies: + react: 19.2.0 + react-native: 0.83.0(@babel/core@7.29.0)(@react-native-community/cli@20.0.0)(@react-native/metro-config@0.83.0(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.0) + react-native-is-edge-to-edge: 1.2.1(react-native@0.83.0(@babel/core@7.29.0)(@react-native-community/cli@20.0.0)(@react-native/metro-config@0.83.0(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.0))(react@19.2.0) + react-native-worklets: 0.7.4(@babel/core@7.29.0)(react-native@0.83.0(@babel/core@7.29.0)(@react-native-community/cli@20.0.0)(@react-native/metro-config@0.83.0(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.0))(react@19.2.0) + semver: 7.7.3 + + react-native-safe-area-context@5.7.0(react-native@0.83.0(@babel/core@7.29.0)(@react-native-community/cli@20.0.0)(@react-native/metro-config@0.83.0(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.0))(react@19.2.0): + dependencies: + react: 19.2.0 + react-native: 0.83.0(@babel/core@7.29.0)(@react-native-community/cli@20.0.0)(@react-native/metro-config@0.83.0(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.0) + + react-native-worklets@0.7.4(@babel/core@7.29.0)(react-native@0.83.0(@babel/core@7.29.0)(@react-native-community/cli@20.0.0)(@react-native/metro-config@0.83.0(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.0))(react@19.2.0): + dependencies: + '@babel/core': 7.29.0 + '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-class-properties': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-classes': 7.28.4(@babel/core@7.29.0) + '@babel/plugin-transform-nullish-coalescing-operator': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-optional-chaining': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-template-literals': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.29.0) + '@babel/preset-typescript': 7.27.1(@babel/core@7.29.0) + convert-source-map: 2.0.0 + react: 19.2.0 + react-native: 0.83.0(@babel/core@7.29.0)(@react-native-community/cli@20.0.0)(@react-native/metro-config@0.83.0(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.0) + semver: 7.7.3 + transitivePeerDependencies: + - supports-color + + react-native@0.83.0(@babel/core@7.29.0)(@react-native-community/cli@20.0.0)(@react-native/metro-config@0.83.0(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.0): + dependencies: + '@jest/create-cache-key-function': 29.7.0 + '@react-native/assets-registry': 0.83.0 + '@react-native/codegen': 0.83.0(@babel/core@7.29.0) + '@react-native/community-cli-plugin': 0.83.0(@react-native-community/cli@20.0.0)(@react-native/metro-config@0.83.0(@babel/core@7.29.0)) + '@react-native/gradle-plugin': 0.83.0 + '@react-native/js-polyfills': 0.83.0 + '@react-native/normalize-colors': 0.83.0 + '@react-native/virtualized-lists': 0.83.0(@types/react@19.2.14)(react-native@0.83.0(@babel/core@7.29.0)(@react-native-community/cli@20.0.0)(@react-native/metro-config@0.83.0(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.0))(react@19.2.0) + abort-controller: 3.0.0 + anser: 1.4.10 + ansi-regex: 5.0.1 + babel-jest: 29.7.0(@babel/core@7.29.0) + babel-plugin-syntax-hermes-parser: 0.32.0 + base64-js: 1.5.1 + commander: 12.1.0 + flow-enums-runtime: 0.0.6 + glob: 7.2.3 + hermes-compiler: 0.14.0 + invariant: 2.2.4 + jest-environment-node: 29.7.0 + memoize-one: 5.2.1 + metro-runtime: 0.83.5 + metro-source-map: 0.83.5 + nullthrows: 1.1.1 + pretty-format: 29.7.0 + promise: 8.3.0 + react: 19.2.0 + react-devtools-core: 6.1.5 + react-refresh: 0.14.2 + regenerator-runtime: 0.13.11 + scheduler: 0.27.0 + semver: 7.7.4 + stacktrace-parser: 0.1.11 + whatwg-fetch: 3.6.20 + ws: 7.5.10 + yargs: 17.7.2 + optionalDependencies: + '@types/react': 19.2.14 + transitivePeerDependencies: + - '@babel/core' + - '@react-native-community/cli' + - '@react-native/metro-config' + - bufferutil + - supports-color + - utf-8-validate + + react-refresh@0.14.2: {} + + react@19.2.0: {} + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + regenerate-unicode-properties@10.2.2: + dependencies: + regenerate: 1.4.2 + + regenerate@1.4.2: {} + + regenerator-runtime@0.13.11: {} + + regexpu-core@6.4.0: + dependencies: + regenerate: 1.4.2 + regenerate-unicode-properties: 10.2.2 + regjsgen: 0.8.0 + regjsparser: 0.13.0 + unicode-match-property-ecmascript: 2.0.0 + unicode-match-property-value-ecmascript: 2.2.1 + + regjsgen@0.8.0: {} + + regjsparser@0.13.0: + dependencies: + jsesc: 3.1.0 + + require-directory@2.1.1: {} + + require-main-filename@2.0.0: {} + + resolve-from@4.0.0: {} + + resolve-from@5.0.0: {} + + resolve@1.22.11: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + restore-cursor@3.1.0: + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + + reusify@1.1.0: {} + + rimraf@3.0.2: + dependencies: + glob: 7.2.3 + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + safe-buffer@5.2.1: {} + + safer-buffer@2.1.2: {} + + scheduler@0.27.0: {} + + semver@6.3.1: {} + + semver@7.7.3: {} + + semver@7.7.4: {} + + send@0.19.2: + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.1 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.2 + transitivePeerDependencies: + - supports-color + + serialize-error@2.1.0: {} + + serve-static@1.16.3: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.19.2 + transitivePeerDependencies: + - supports-color + + set-blocking@2.0.0: {} + + setprototypeof@1.2.0: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + shell-quote@1.8.3: {} + + side-channel-list@1.0.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.0 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + signal-exit@3.0.7: {} + + signal-exit@4.1.0: {} + + sisteransi@1.0.5: {} + + slash@3.0.0: {} + + slice-ansi@2.1.0: + dependencies: + ansi-styles: 3.2.1 + astral-regex: 1.0.0 + is-fullwidth-code-point: 2.0.0 + + source-map-support@0.5.21: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map@0.5.7: {} + + source-map@0.6.1: {} + + sprintf-js@1.0.3: {} + + stack-utils@2.0.6: + dependencies: + escape-string-regexp: 2.0.0 + + stackframe@1.3.4: {} + + stacktrace-parser@0.1.11: + dependencies: + type-fest: 0.7.1 + + statuses@1.5.0: {} + + statuses@2.0.2: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.2.0 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + strip-ansi@5.2.0: + dependencies: + ansi-regex: 4.1.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.2.0: + dependencies: + ansi-regex: 6.2.2 + + strip-final-newline@2.0.0: {} + + strnum@1.1.2: {} + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + terser@5.46.0: + dependencies: + '@jridgewell/source-map': 0.3.11 + acorn: 8.16.0 + commander: 2.20.3 + source-map-support: 0.5.21 + + test-exclude@6.0.0: + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 7.2.3 + minimatch: 3.1.5 + + throat@5.0.0: {} + + tmpl@1.0.5: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + toidentifier@1.0.1: {} + + type-detect@4.0.8: {} + + type-fest@0.7.1: {} + + type-is@1.6.18: + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + + unc-path-regex@0.1.2: {} + + undici-types@7.18.2: {} + + unicode-canonical-property-names-ecmascript@2.0.1: {} + + unicode-match-property-ecmascript@2.0.0: + dependencies: + unicode-canonical-property-names-ecmascript: 2.0.1 + unicode-property-aliases-ecmascript: 2.2.0 + + unicode-match-property-value-ecmascript@2.2.1: {} + + unicode-property-aliases-ecmascript@2.2.0: {} + + universalify@0.1.2: {} + + universalify@2.0.1: {} + + unpipe@1.0.0: {} + + update-browserslist-db@1.2.3(browserslist@4.28.1): + dependencies: + browserslist: 4.28.1 + escalade: 3.2.0 + picocolors: 1.1.1 + + util-deprecate@1.0.2: {} + + utils-merge@1.0.1: {} + + vary@1.1.2: {} + + vlq@1.0.1: {} + + walker@1.0.8: + dependencies: + makeerror: 1.0.12 + + wcwidth@1.0.1: + dependencies: + defaults: 1.0.4 + + whatwg-fetch@3.6.20: {} + + which-module@2.0.1: {} + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + wrap-ansi@6.2.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.3 + string-width: 5.1.2 + strip-ansi: 7.2.0 + + wrappy@1.0.2: {} + + write-file-atomic@4.0.2: + dependencies: + imurmurhash: 0.1.4 + signal-exit: 3.0.7 + + ws@6.2.3: + dependencies: + async-limiter: 1.0.1 + + ws@7.5.10: {} + + y18n@4.0.3: {} + + y18n@5.0.8: {} + + yallist@3.1.1: {} + + yaml@2.8.2: {} + + yargs-parser@18.1.3: + dependencies: + camelcase: 5.3.1 + decamelize: 1.2.0 + + yargs-parser@21.1.1: {} + + yargs@15.4.1: + dependencies: + cliui: 6.0.0 + decamelize: 1.2.0 + find-up: 4.1.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + require-main-filename: 2.0.0 + set-blocking: 2.0.0 + string-width: 4.2.3 + which-module: 2.0.1 + y18n: 4.0.3 + yargs-parser: 18.1.3 + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + yocto-queue@0.1.0: {} diff --git a/example/src/demos/PerPropertyDemo.tsx b/example/src/demos/PerPropertyDemo.tsx new file mode 100644 index 0000000..4c7609d --- /dev/null +++ b/example/src/demos/PerPropertyDemo.tsx @@ -0,0 +1,50 @@ +import { useState } from 'react'; +import { Text, StyleSheet } from 'react-native'; +import { EaseView } from 'react-native-ease'; + +import { Section } from '../components/Section'; +import { Button } from '../components/Button'; + +export function PerPropertyDemo() { + const [active, setActive] = useState(false); + return ( +
+ + Opacity fades with timing 150ms, translateX springs independently + + +
+ ); +} + +const styles = StyleSheet.create({ + box: { + width: 80, + height: 80, + backgroundColor: '#4a90d9', + borderRadius: 12, + borderWidth: 2, + borderColor: '#7ab8ff', + alignItems: 'center', + justifyContent: 'center', + }, + hint: { + fontSize: 13, + color: '#8888aa', + marginBottom: 12, + }, +}); diff --git a/example/src/demos/index.ts b/example/src/demos/index.ts index c97dd27..4f35bfd 100644 --- a/example/src/demos/index.ts +++ b/example/src/demos/index.ts @@ -19,6 +19,7 @@ import { SlideDemo } from './SlideDemo'; import { StyleReRenderDemo } from './StyleReRenderDemo'; import { StyledCardDemo } from './StyledCardDemo'; import { TransformOriginDemo } from './TransformOriginDemo'; +import { PerPropertyDemo } from './PerPropertyDemo'; interface DemoEntry { component: ComponentType; @@ -35,6 +36,7 @@ export const demos: Record = { 'rotate': { component: RotateDemo, title: 'Rotate', section: 'Transform' }, 'scale': { component: ScaleDemo, title: 'Scale', section: 'Transform' }, 'transform-origin': { + 'per-property': { component: PerPropertyDemo, title: 'Per-Property', section: 'Advanced' }, component: TransformOriginDemo, title: 'Transform Origin', section: 'Transform', diff --git a/ios/EaseView.mm b/ios/EaseView.mm index 684958f..753729e 100644 --- a/ios/EaseView.mm +++ b/ios/EaseView.mm @@ -58,6 +58,124 @@ static CATransform3D composeTransform(CGFloat scaleX, CGFloat scaleY, kMaskScaleX | kMaskScaleY | kMaskRotate | kMaskRotateX | kMaskRotateY; +// Per-property transition config resolved from arrays or scalar fallback +struct EaseTransitionConfig { + EaseViewTransitionType type; + int duration; + float bezier[4]; + float damping; + float stiffness; + float mass; + EaseViewTransitionLoop loop; +}; + +static EaseTransitionConfig +transitionConfigForPropertyIndex(int index, const EaseViewProps &props) { + const auto &types = props.perPropertyTransitionTypes; + if (!types.empty() && index < (int)types.size()) { + EaseTransitionConfig config; + // Type + const auto &typeStr = types[index]; + if (typeStr == "spring") { + config.type = EaseViewTransitionType::Spring; + } else if (typeStr == "none") { + config.type = EaseViewTransitionType::None; + } else { + config.type = EaseViewTransitionType::Timing; + } + // Duration + const auto &durations = props.perPropertyTransitionDurations; + config.duration = (index < (int)durations.size()) ? durations[index] : 300; + // Bezier (4 values per property) + const auto &beziers = props.perPropertyTransitionEasingBeziers; + int bIdx = index * 4; + if (bIdx + 3 < (int)beziers.size()) { + config.bezier[0] = beziers[bIdx]; + config.bezier[1] = beziers[bIdx + 1]; + config.bezier[2] = beziers[bIdx + 2]; + config.bezier[3] = beziers[bIdx + 3]; + } else { + config.bezier[0] = 0.42f; + config.bezier[1] = 0.0f; + config.bezier[2] = 0.58f; + config.bezier[3] = 1.0f; + } + // Damping + const auto &dampings = props.perPropertyTransitionDampings; + config.damping = (index < (int)dampings.size()) ? dampings[index] : 15.0f; + // Stiffness + const auto &stiffnesses = props.perPropertyTransitionStiffnesses; + config.stiffness = + (index < (int)stiffnesses.size()) ? stiffnesses[index] : 120.0f; + // Mass + const auto &masses = props.perPropertyTransitionMasses; + config.mass = (index < (int)masses.size()) ? masses[index] : 1.0f; + // Loop + const auto &loops = props.perPropertyTransitionLoops; + if (index < (int)loops.size()) { + const auto &loopStr = loops[index]; + if (loopStr == "repeat") { + config.loop = EaseViewTransitionLoop::Repeat; + } else if (loopStr == "reverse") { + config.loop = EaseViewTransitionLoop::Reverse; + } else { + config.loop = EaseViewTransitionLoop::None; + } + } else { + config.loop = EaseViewTransitionLoop::None; + } + return config; + } + // Fallback to scalar props + EaseTransitionConfig config; + config.type = props.transitionType; + config.duration = props.transitionDuration; + const auto &b = props.transitionEasingBezier; + if (b.size() == 4) { + config.bezier[0] = b[0]; + config.bezier[1] = b[1]; + config.bezier[2] = b[2]; + config.bezier[3] = b[3]; + } else { + config.bezier[0] = 0.42f; + config.bezier[1] = 0.0f; + config.bezier[2] = 0.58f; + config.bezier[3] = 1.0f; + } + config.damping = props.transitionDamping; + config.stiffness = props.transitionStiffness; + config.mass = props.transitionMass; + config.loop = props.transitionLoop; + return config; +} + +// Property indices matching JS constants +static const int kPropIndexOpacity = 0; +static const int kPropIndexTranslateX = 1; +// static const int kPropIndexTranslateY = 2; +// static const int kPropIndexScaleX = 3; +// static const int kPropIndexScaleY = 4; +// static const int kPropIndexRotate = 5; +// static const int kPropIndexRotateX = 6; +// static const int kPropIndexRotateY = 7; +static const int kPropIndexBorderRadius = 8; +static const int kPropIndexBackgroundColor = 9; + +// Check if per-property arrays are populated +static BOOL hasPerPropertyArrays(const EaseViewProps &props) { + return !props.perPropertyTransitionTypes.empty(); +} + +// Find lowest property index with a set mask bit among transform properties +static int lowestTransformPropertyIndex(int mask) { + for (int i = 1; i <= 7; i++) { + if (mask & (1 << i)) { + return i; + } + } + return 1; // fallback to translateX +} + @implementation EaseView { BOOL _isFirstMount; NSInteger _animationBatchId; @@ -139,16 +257,16 @@ - (NSValue *)presentationValueForKeyPath:(NSString *)keyPath { - (CAAnimation *)createAnimationForKeyPath:(NSString *)keyPath fromValue:(NSValue *)fromValue toValue:(NSValue *)toValue - props:(const EaseViewProps &)props + config:(EaseTransitionConfig)config loop:(BOOL)loop { - if (props.transitionType == EaseViewTransitionType::Spring) { + if (config.type == EaseViewTransitionType::Spring) { CASpringAnimation *spring = [CASpringAnimation animationWithKeyPath:keyPath]; spring.fromValue = fromValue; spring.toValue = toValue; - spring.damping = props.transitionDamping; - spring.stiffness = props.transitionStiffness; - spring.mass = props.transitionMass; + spring.damping = config.damping; + spring.stiffness = config.stiffness; + spring.mass = config.mass; spring.initialVelocity = 0; spring.duration = spring.settlingDuration; return spring; @@ -156,23 +274,14 @@ - (CAAnimation *)createAnimationForKeyPath:(NSString *)keyPath CABasicAnimation *timing = [CABasicAnimation animationWithKeyPath:keyPath]; timing.fromValue = fromValue; timing.toValue = toValue; - timing.duration = props.transitionDuration / 1000.0; - { - const auto &b = props.transitionEasingBezier; - if (b.size() == 4) { - timing.timingFunction = [CAMediaTimingFunction - functionWithControlPoints:(float)b[0]:(float)b[1]:(float)b[2 - ]:(float)b[3]]; - } else { - // Fallback: easeInOut - timing.timingFunction = - [CAMediaTimingFunction functionWithControlPoints:0.42:0.0:0.58:1.0]; - } - } + timing.duration = config.duration / 1000.0; + timing.timingFunction = [CAMediaTimingFunction + functionWithControlPoints:config.bezier[0]:config.bezier[1 + ]:config.bezier[2]:config.bezier[3]]; if (loop) { - if (props.transitionLoop == EaseViewTransitionLoop::Repeat) { + if (config.loop == EaseViewTransitionLoop::Repeat) { timing.repeatCount = HUGE_VALF; - } else if (props.transitionLoop == EaseViewTransitionLoop::Reverse) { + } else if (config.loop == EaseViewTransitionLoop::Reverse) { timing.repeatCount = HUGE_VALF; timing.autoreverses = YES; } @@ -185,14 +294,14 @@ - (void)applyAnimationForKeyPath:(NSString *)keyPath animationKey:(NSString *)animationKey fromValue:(NSValue *)fromValue toValue:(NSValue *)toValue - props:(const EaseViewProps &)props + config:(EaseTransitionConfig)config loop:(BOOL)loop { _pendingAnimationCount++; CAAnimation *animation = [self createAnimationForKeyPath:keyPath fromValue:fromValue toValue:toValue - props:props + config:config loop:loop]; if (props.transitionDelay > 0) { animation.beginTime = @@ -257,6 +366,8 @@ - (void)updateProps:(const Props::Shared &)props int mask = newViewProps.animatedProperties; BOOL hasTransform = (mask & kMaskAnyTransform) != 0; + BOOL perProp = hasPerPropertyArrays(newViewProps); + if (_isFirstMount) { _isFirstMount = NO; @@ -305,34 +416,43 @@ - (void)updateProps:(const Props::Shared &)props // Animate from initial to target if (hasInitialOpacity) { + EaseTransitionConfig opacityConfig = + transitionConfigForPropertyIndex(kPropIndexOpacity, newViewProps); self.layer.opacity = newViewProps.animateOpacity; [self applyAnimationForKeyPath:@"opacity" animationKey:kAnimKeyOpacity fromValue:@(newViewProps.initialAnimateOpacity) toValue:@(newViewProps.animateOpacity) - props:newViewProps + config:opacityConfig loop:YES]; } if (hasInitialTransform) { + int transformIdx = lowestTransformPropertyIndex(mask); + EaseTransitionConfig transformConfig = + transitionConfigForPropertyIndex(transformIdx, newViewProps); self.layer.transform = targetT; [self applyAnimationForKeyPath:@"transform" animationKey:kAnimKeyTransform fromValue:[NSValue valueWithCATransform3D:initialT] toValue:[NSValue valueWithCATransform3D:targetT] - props:newViewProps + config:transformConfig loop:YES]; } if (hasInitialBorderRadius) { + EaseTransitionConfig brConfig = transitionConfigForPropertyIndex( + kPropIndexBorderRadius, newViewProps); self.layer.cornerRadius = newViewProps.animateBorderRadius; [self applyAnimationForKeyPath:@"cornerRadius" animationKey:kAnimKeyCornerRadius fromValue:@(newViewProps.initialAnimateBorderRadius) toValue:@(newViewProps.animateBorderRadius) - props:newViewProps + config:brConfig loop:YES]; } if (hasInitialBackgroundColor) { + EaseTransitionConfig bgConfig = transitionConfigForPropertyIndex( + kPropIndexBackgroundColor, newViewProps); self.layer.backgroundColor = RCTUIColorFromSharedColor(newViewProps.animateBackgroundColor) .CGColor; @@ -345,7 +465,7 @@ - (void)updateProps:(const Props::Shared &)props toValue:(__bridge id)RCTUIColorFromSharedColor( newViewProps.animateBackgroundColor) .CGColor - props:newViewProps + config:bgConfig loop:YES]; } } else { @@ -363,8 +483,9 @@ - (void)updateProps:(const Props::Shared &)props RCTUIColorFromSharedColor(newViewProps.animateBackgroundColor) .CGColor; } - } else if (newViewProps.transitionType == EaseViewTransitionType::None) { - // No transition — set values immediately + } else if (!perProp && + newViewProps.transitionType == EaseViewTransitionType::None) { + // No transition (scalar) — set values immediately [self.layer removeAllAnimations]; if (mask & kMaskOpacity) self.layer.opacity = newViewProps.animateOpacity; @@ -392,14 +513,22 @@ - (void)updateProps:(const Props::Shared &)props if ((mask & kMaskOpacity) && oldViewProps.animateOpacity != newViewProps.animateOpacity) { - self.layer.opacity = newViewProps.animateOpacity; - [self - applyAnimationForKeyPath:@"opacity" - animationKey:kAnimKeyOpacity - fromValue:[self presentationValueForKeyPath:@"opacity"] - toValue:@(newViewProps.animateOpacity) - props:newViewProps - loop:NO]; + EaseTransitionConfig opacityConfig = + transitionConfigForPropertyIndex(kPropIndexOpacity, newViewProps); + if (opacityConfig.type == EaseViewTransitionType::None) { + self.layer.opacity = newViewProps.animateOpacity; + [self.layer removeAnimationForKey:kAnimKeyOpacity]; + } else { + self.layer.opacity = newViewProps.animateOpacity; + [self + applyAnimationForKeyPath:@"opacity" + animationKey:kAnimKeyOpacity + fromValue:[self + presentationValueForKeyPath:@"opacity"] + toValue:@(newViewProps.animateOpacity) + config:opacityConfig + loop:NO]; + } } // Check if ANY transform-related property changed @@ -414,46 +543,84 @@ - (void)updateProps:(const Props::Shared &)props oldViewProps.animateRotateY != newViewProps.animateRotateY; if (anyTransformChanged) { - CATransform3D fromT = [self presentationTransform]; - CATransform3D toT = [self targetTransformFromProps:newViewProps]; - self.layer.transform = toT; - [self applyAnimationForKeyPath:@"transform" - animationKey:kAnimKeyTransform - fromValue:[NSValue valueWithCATransform3D:fromT] - toValue:[NSValue valueWithCATransform3D:toT] - props:newViewProps - loop:NO]; + // Determine which transform sub-properties changed for config selection + int changedTransformMask = 0; + if (oldViewProps.animateTranslateX != newViewProps.animateTranslateX) + changedTransformMask |= kMaskTranslateX; + if (oldViewProps.animateTranslateY != newViewProps.animateTranslateY) + changedTransformMask |= kMaskTranslateY; + if (oldViewProps.animateScaleX != newViewProps.animateScaleX) + changedTransformMask |= kMaskScaleX; + if (oldViewProps.animateScaleY != newViewProps.animateScaleY) + changedTransformMask |= kMaskScaleY; + if (oldViewProps.animateRotate != newViewProps.animateRotate) + changedTransformMask |= kMaskRotate; + if (oldViewProps.animateRotateX != newViewProps.animateRotateX) + changedTransformMask |= kMaskRotateX; + if (oldViewProps.animateRotateY != newViewProps.animateRotateY) + changedTransformMask |= kMaskRotateY; + + int transformIdx = lowestTransformPropertyIndex(changedTransformMask); + EaseTransitionConfig transformConfig = + transitionConfigForPropertyIndex(transformIdx, newViewProps); + + if (transformConfig.type == EaseViewTransitionType::None) { + self.layer.transform = [self targetTransformFromProps:newViewProps]; + [self.layer removeAnimationForKey:kAnimKeyTransform]; + } else { + CATransform3D fromT = [self presentationTransform]; + CATransform3D toT = [self targetTransformFromProps:newViewProps]; + self.layer.transform = toT; + [self applyAnimationForKeyPath:@"transform" + animationKey:kAnimKeyTransform + fromValue:[NSValue valueWithCATransform3D:fromT] + toValue:[NSValue valueWithCATransform3D:toT] + config:transformConfig + loop:NO]; + } } } if ((mask & kMaskBorderRadius) && oldViewProps.animateBorderRadius != newViewProps.animateBorderRadius) { + EaseTransitionConfig brConfig = transitionConfigForPropertyIndex( + kPropIndexBorderRadius, newViewProps); self.layer.cornerRadius = newViewProps.animateBorderRadius; self.layer.masksToBounds = newViewProps.animateBorderRadius > 0; - [self applyAnimationForKeyPath:@"cornerRadius" - animationKey:kAnimKeyCornerRadius - fromValue:[self presentationValueForKeyPath: - @"cornerRadius"] - toValue:@(newViewProps.animateBorderRadius) - props:newViewProps - loop:NO]; + if (brConfig.type == EaseViewTransitionType::None) { + [self.layer removeAnimationForKey:kAnimKeyCornerRadius]; + } else { + [self applyAnimationForKeyPath:@"cornerRadius" + animationKey:kAnimKeyCornerRadius + fromValue:[self presentationValueForKeyPath: + @"cornerRadius"] + toValue:@(newViewProps.animateBorderRadius) + config:brConfig + loop:NO]; + } } if ((mask & kMaskBackgroundColor) && oldViewProps.animateBackgroundColor != newViewProps.animateBackgroundColor) { - CGColorRef fromColor = (__bridge CGColorRef) - [self presentationValueForKeyPath:@"backgroundColor"]; + EaseTransitionConfig bgConfig = transitionConfigForPropertyIndex( + kPropIndexBackgroundColor, newViewProps); CGColorRef toColor = RCTUIColorFromSharedColor(newViewProps.animateBackgroundColor) .CGColor; self.layer.backgroundColor = toColor; - [self applyAnimationForKeyPath:@"backgroundColor" - animationKey:kAnimKeyBackgroundColor - fromValue:(__bridge id)fromColor - toValue:(__bridge id)toColor - props:newViewProps - loop:NO]; + if (bgConfig.type == EaseViewTransitionType::None) { + [self.layer removeAnimationForKey:kAnimKeyBackgroundColor]; + } else { + CGColorRef fromColor = (__bridge CGColorRef) + [self presentationValueForKeyPath:@"backgroundColor"]; + [self applyAnimationForKeyPath:@"backgroundColor" + animationKey:kAnimKeyBackgroundColor + fromValue:(__bridge id)fromColor + toValue:(__bridge id)toColor + config:bgConfig + loop:NO]; + } } } diff --git a/src/EaseView.tsx b/src/EaseView.tsx index bb34193..a40789e 100644 --- a/src/EaseView.tsx +++ b/src/EaseView.tsx @@ -3,6 +3,7 @@ import NativeEaseView from './EaseViewNativeComponent'; import type { AnimateProps, CubicBezier, + SingleTransition, Transition, TransitionEndEvent, TransformOrigin, @@ -58,6 +59,125 @@ const EASING_PRESETS: Record = { easeInOut: [0.42, 0, 0.58, 1], }; +/** Property index order for per-property arrays. */ +const PROPERTY_KEYS: (keyof AnimateProps)[] = [ + 'opacity', + 'translateX', + 'translateY', + 'scaleX', + 'scaleY', + 'rotate', + 'rotateX', + 'rotateY', + 'borderRadius', + 'backgroundColor', +]; + +const PROPERTY_COUNT = PROPERTY_KEYS.length; + +/** Returns true if the transition is a SingleTransition (has a `type` field). */ +function isSingleTransition(t: Transition): t is SingleTransition { + return 'type' in t; +} + +/** Library defaults: spring for transforms (indices 1-7), timing 300ms easeInOut for others. */ +const TIMING_DEFAULT: SingleTransition = { + type: 'timing', + duration: 300, + easing: 'easeInOut', +}; +const SPRING_DEFAULT: SingleTransition = { + type: 'spring', + damping: 15, + stiffness: 120, + mass: 1, +}; + +function getLibraryDefault(index: number): SingleTransition { + // Indices 1-7 are transforms → spring default + // Indices 0,8,9 are opacity, borderRadius, backgroundColor → timing default + return index >= 1 && index <= 7 ? SPRING_DEFAULT : TIMING_DEFAULT; +} + +/** Resolve a SingleTransition into flat scalar values. */ +function resolveSingleConfig(config: SingleTransition) { + const type = config.type as 'timing' | 'spring' | 'none'; + const duration = config.type === 'timing' ? config.duration ?? 300 : 300; + const rawEasing = + config.type === 'timing' ? config.easing ?? 'easeInOut' : 'easeInOut'; + const bezier: CubicBezier = Array.isArray(rawEasing) + ? rawEasing + : EASING_PRESETS[rawEasing]!; + const damping = config.type === 'spring' ? config.damping ?? 15 : 15; + const stiffness = config.type === 'spring' ? config.stiffness ?? 120 : 120; + const mass = config.type === 'spring' ? config.mass ?? 1 : 1; + const loop: 'none' | 'repeat' | 'reverse' = + config.type === 'timing' ? config.loop ?? 'none' : 'none'; + return { type, duration, bezier, damping, stiffness, mass, loop }; +} + +interface PerPropertyArrays { + types: string[]; + durations: number[]; + dampings: number[]; + stiffnesses: number[]; + masses: number[]; + loops: string[]; + easingBeziers: number[]; +} + +function resolvePerPropertyTransitions( + transitionMap: Exclude, +): { + scalars: ReturnType; + arrays: PerPropertyArrays; +} { + const arrays: PerPropertyArrays = { + types: [], + durations: [], + dampings: [], + stiffnesses: [], + masses: [], + loops: [], + easingBeziers: [], + }; + + const defaultConfig = transitionMap.default; + + for (let i = 0; i < PROPERTY_COUNT; i++) { + const key = PROPERTY_KEYS[i]!; + // Resolution order: specific key → scale shorthand (for scaleX/scaleY) → default → library default + let config: SingleTransition; + if (transitionMap[key] != null) { + config = transitionMap[key]!; + } else if ( + (key === 'scaleX' || key === 'scaleY') && + transitionMap.scale != null + ) { + config = transitionMap.scale!; + } else if (defaultConfig != null) { + config = defaultConfig; + } else { + config = getLibraryDefault(i); + } + + const resolved = resolveSingleConfig(config); + arrays.types.push(resolved.type); + arrays.durations.push(resolved.duration); + arrays.dampings.push(resolved.damping); + arrays.stiffnesses.push(resolved.stiffness); + arrays.masses.push(resolved.mass); + arrays.loops.push(resolved.loop); + arrays.easingBeziers.push(...resolved.bezier); + } + + // Scalar props = default key values (or library defaults for opacity category) + const scalarConfig = defaultConfig ?? TIMING_DEFAULT; + const scalars = resolveSingleConfig(scalarConfig); + + return { scalars, arrays }; +} + export type EaseViewProps = ViewProps & { /** Target values for animated properties. */ animate?: AnimateProps; @@ -179,34 +299,74 @@ export function EaseView({ } } - // Resolve transition config - const transitionType = transition?.type ?? 'timing'; - const transitionDuration = - transition?.type === 'timing' ? transition.duration ?? 300 : 300; - const rawEasing = - transition?.type === 'timing' - ? transition.easing ?? 'easeInOut' - : 'easeInOut'; - if (__DEV__) { - if (Array.isArray(rawEasing)) { - if ((rawEasing as number[]).length !== 4) { - console.warn( - 'react-native-ease: Custom easing must be a [x1, y1, x2, y2] tuple (got length ' + - (rawEasing as number[]).length + - ').', - ); - } - if ( - rawEasing[0] < 0 || - rawEasing[0] > 1 || - rawEasing[2] < 0 || - rawEasing[2] > 1 - ) { - console.warn( - 'react-native-ease: Easing x-values (x1, x2) must be between 0 and 1.', - ); + // Resolve transition config — single config or per-property map + const isMap = transition != null && !isSingleTransition(transition); + const singleTransition = transition == null || isMap ? undefined : transition; + + // Single config resolution (used when single transition or as scalars for map) + let transitionType: 'timing' | 'spring' | 'none'; + let transitionDuration: number; + let bezier: CubicBezier; + let transitionDamping: number; + let transitionStiffness: number; + let transitionMass: number; + let transitionLoop: 'none' | 'repeat' | 'reverse'; + let perPropertyArrays: PerPropertyArrays | undefined; + + if (isMap) { + const { scalars, arrays } = resolvePerPropertyTransitions(transition); + transitionType = scalars.type; + transitionDuration = scalars.duration; + bezier = scalars.bezier; + transitionDamping = scalars.damping; + transitionStiffness = scalars.stiffness; + transitionMass = scalars.mass; + transitionLoop = scalars.loop; + perPropertyArrays = arrays; + } else { + transitionType = singleTransition?.type ?? 'timing'; + transitionDuration = + singleTransition?.type === 'timing' + ? singleTransition.duration ?? 300 + : 300; + const rawEasing = + singleTransition?.type === 'timing' + ? singleTransition.easing ?? 'easeInOut' + : 'easeInOut'; + if (__DEV__) { + if (Array.isArray(rawEasing)) { + if ((rawEasing as number[]).length !== 4) { + console.warn( + 'react-native-ease: Custom easing must be a [x1, y1, x2, y2] tuple (got length ' + + (rawEasing as number[]).length + + ').', + ); + } + if ( + rawEasing[0] < 0 || + rawEasing[0] > 1 || + rawEasing[2] < 0 || + rawEasing[2] > 1 + ) { + console.warn( + 'react-native-ease: Easing x-values (x1, x2) must be between 0 and 1.', + ); + } } } + bezier = Array.isArray(rawEasing) ? rawEasing : EASING_PRESETS[rawEasing]!; + transitionDamping = + singleTransition?.type === 'spring' ? singleTransition.damping ?? 15 : 15; + transitionStiffness = + singleTransition?.type === 'spring' + ? singleTransition.stiffness ?? 120 + : 120; + transitionMass = + singleTransition?.type === 'spring' ? singleTransition.mass ?? 1 : 1; + transitionLoop = + singleTransition?.type === 'timing' + ? singleTransition.loop ?? 'none' + : 'none'; } const bezier: CubicBezier = Array.isArray(rawEasing) ? rawEasing @@ -224,6 +384,7 @@ export function EaseView({ ? transition.delay ?? 0 : 0; + const handleTransitionEnd = onTransitionEnd ? (event: { nativeEvent: { finished: boolean } }) => onTransitionEnd(event.nativeEvent) @@ -262,6 +423,14 @@ export function EaseView({ transitionMass={transitionMass} transitionLoop={transitionLoop} transitionDelay={transitionDelay} + perPropertyTransitionTypes={perPropertyArrays?.types} + perPropertyTransitionDurations={perPropertyArrays?.durations} + perPropertyTransitionDampings={perPropertyArrays?.dampings} + perPropertyTransitionStiffnesses={perPropertyArrays?.stiffnesses} + perPropertyTransitionMasses={perPropertyArrays?.masses} + perPropertyTransitionLoops={perPropertyArrays?.loops} + perPropertyTransitionEasingBeziers={perPropertyArrays?.easingBeziers} + useHardwareLayer={useHardwareLayer} transformOriginX={transformOrigin?.x ?? 0.5} transformOriginY={transformOrigin?.y ?? 0.5} diff --git a/src/EaseViewNativeComponent.ts b/src/EaseViewNativeComponent.ts index ad9e313..d12190e 100644 --- a/src/EaseViewNativeComponent.ts +++ b/src/EaseViewNativeComponent.ts @@ -54,6 +54,17 @@ export interface NativeProps extends ViewProps { >; transitionDelay?: CodegenTypes.WithDefault; + // Per-property transition arrays (10 elements each, one per animatable property) + // Index order: 0=opacity, 1=translateX, 2=translateY, 3=scaleX, 4=scaleY, + // 5=rotate, 6=rotateX, 7=rotateY, 8=borderRadius, 9=backgroundColor + perPropertyTransitionTypes?: ReadonlyArray; + perPropertyTransitionDurations?: ReadonlyArray; + perPropertyTransitionDampings?: ReadonlyArray; + perPropertyTransitionStiffnesses?: ReadonlyArray; + perPropertyTransitionMasses?: ReadonlyArray; + perPropertyTransitionLoops?: ReadonlyArray; + perPropertyTransitionEasingBeziers?: ReadonlyArray; // 40 elements (4 per property) + // Transform origin (0–1 fractions, default center) transformOriginX?: CodegenTypes.WithDefault; transformOriginY?: CodegenTypes.WithDefault; diff --git a/src/__tests__/EaseView.test.tsx b/src/__tests__/EaseView.test.tsx index 7d3bc18..dfc3526 100644 --- a/src/__tests__/EaseView.test.tsx +++ b/src/__tests__/EaseView.test.tsx @@ -458,4 +458,146 @@ describe('EaseView', () => { ); }); }); + + describe('per-property transition map', () => { + it('does not pass arrays for single transition (backward compat)', () => { + render( + , + ); + const props = getNativeProps(); + expect(props.perPropertyTransitionTypes).toBeUndefined(); + expect(props.perPropertyTransitionDurations).toBeUndefined(); + expect(props.perPropertyTransitionDampings).toBeUndefined(); + expect(props.perPropertyTransitionStiffnesses).toBeUndefined(); + expect(props.perPropertyTransitionMasses).toBeUndefined(); + expect(props.perPropertyTransitionLoops).toBeUndefined(); + expect(props.perPropertyTransitionEasingBeziers).toBeUndefined(); + }); + + it('populates arrays with default-only map (all slots same)', () => { + render( + , + ); + const props = getNativeProps(); + expect(props.perPropertyTransitionTypes).toHaveLength(10); + expect(props.perPropertyTransitionTypes).toEqual( + Array(10).fill('timing'), + ); + expect(props.perPropertyTransitionDurations).toEqual(Array(10).fill(500)); + // Scalar props should match default + expect(props.transitionType).toBe('timing'); + expect(props.transitionDuration).toBe(500); + }); + + it('applies property-specific overrides', () => { + render( + , + ); + const props = getNativeProps(); + // Index 0 = opacity: timing 150ms + expect(props.perPropertyTransitionTypes[0]).toBe('timing'); + expect(props.perPropertyTransitionDurations[0]).toBe(150); + // Index 2 = translateY: spring + expect(props.perPropertyTransitionTypes[2]).toBe('spring'); + expect(props.perPropertyTransitionDampings[2]).toBe(20); + expect(props.perPropertyTransitionStiffnesses[2]).toBe(200); + // Index 1 = translateX: default timing 300ms + expect(props.perPropertyTransitionTypes[1]).toBe('timing'); + expect(props.perPropertyTransitionDurations[1]).toBe(300); + }); + + it('applies scale shorthand to scaleX and scaleY', () => { + render( + , + ); + const props = getNativeProps(); + // Index 3 = scaleX, Index 4 = scaleY + expect(props.perPropertyTransitionTypes[3]).toBe('spring'); + expect(props.perPropertyTransitionTypes[4]).toBe('spring'); + expect(props.perPropertyTransitionDampings[3]).toBe(10); + expect(props.perPropertyTransitionDampings[4]).toBe(10); + }); + + it('allows scaleX to override scale shorthand', () => { + render( + , + ); + const props = getNativeProps(); + // scaleX (index 3) uses specific override + expect(props.perPropertyTransitionTypes[3]).toBe('timing'); + expect(props.perPropertyTransitionDurations[3]).toBe(200); + // scaleY (index 4) falls back to scale shorthand + expect(props.perPropertyTransitionTypes[4]).toBe('spring'); + expect(props.perPropertyTransitionDampings[4]).toBe(10); + }); + + it('uses library defaults by category when no default key', () => { + render( + , + ); + const props = getNativeProps(); + // opacity (index 0) is explicitly set + expect(props.perPropertyTransitionTypes[0]).toBe('timing'); + expect(props.perPropertyTransitionDurations[0]).toBe(150); + // translateX (index 1) — transform category → spring default + expect(props.perPropertyTransitionTypes[1]).toBe('spring'); + expect(props.perPropertyTransitionDampings[1]).toBe(15); + expect(props.perPropertyTransitionStiffnesses[1]).toBe(120); + // borderRadius (index 8) — non-transform → timing default + expect(props.perPropertyTransitionTypes[8]).toBe('timing'); + expect(props.perPropertyTransitionDurations[8]).toBe(300); + // backgroundColor (index 9) — non-transform → timing default + expect(props.perPropertyTransitionTypes[9]).toBe('timing'); + }); + + it('flattens easing beziers into 40-element array', () => { + render( + , + ); + const props = getNativeProps(); + expect(props.perPropertyTransitionEasingBeziers).toHaveLength(40); + // linear = [0, 0, 1, 1] repeated 10 times + for (let i = 0; i < 10; i++) { + expect(props.perPropertyTransitionEasingBeziers[i * 4]).toBe(0); + expect(props.perPropertyTransitionEasingBeziers[i * 4 + 1]).toBe(0); + expect(props.perPropertyTransitionEasingBeziers[i * 4 + 2]).toBe(1); + expect(props.perPropertyTransitionEasingBeziers[i * 4 + 3]).toBe(1); + } + }); + }); }); diff --git a/src/index.tsx b/src/index.tsx index 739b0d6..0f260e2 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -4,6 +4,8 @@ export type { AnimateProps, CubicBezier, Transition, + SingleTransition, + TransitionMap, TimingTransition, SpringTransition, NoneTransition, diff --git a/src/types.ts b/src/types.ts index f1b35a2..69cfee4 100644 --- a/src/types.ts +++ b/src/types.ts @@ -42,8 +42,20 @@ export type NoneTransition = { type: 'none'; }; -/** Animation transition configuration. */ -export type Transition = TimingTransition | SpringTransition | NoneTransition; +/** A single animation transition configuration. */ +export type SingleTransition = + | TimingTransition + | SpringTransition + | NoneTransition; + +/** Per-property transition map. Each key overrides the transition for that animatable property. */ +export type TransitionMap = { + /** Fallback config for properties not explicitly listed. */ + default?: SingleTransition; +} & Partial>; + +/** Animation transition configuration — either a single config or a per-property map. */ +export type Transition = SingleTransition | TransitionMap; /** Event fired when the animation ends. */ export type TransitionEndEvent = { From 70e348914870ab2c15aae0db3077b3a89289d191 Mon Sep 17 00:00:00 2001 From: EQuimper Date: Sat, 14 Mar 2026 09:51:18 -0400 Subject: [PATCH 2/6] feat: implement immediate transition end for 'none' config in per-property animations --- android/src/main/java/com/ease/EaseView.kt | 73 +++++++++++++++++- ios/EaseView.mm | 88 +++++++++++++++++----- 2 files changed, 140 insertions(+), 21 deletions(-) diff --git a/android/src/main/java/com/ease/EaseView.kt b/android/src/main/java/com/ease/EaseView.kt index 3896441..1c4cf39 100644 --- a/android/src/main/java/com/ease/EaseView.kt +++ b/android/src/main/java/com/ease/EaseView.kt @@ -336,6 +336,12 @@ class EaseView(context: Context) : ReactViewGroup(context) { if (mask and MASK_BACKGROUND_COLOR != 0 && initialAnimateBackgroundColor != backgroundColor) { animateBackgroundColor(initialAnimateBackgroundColor, backgroundColor, getTransitionConfigForProperty(PROP_INDEX_BACKGROUND_COLOR), loop = true) } + + // If all per-property configs were 'none', no animations were queued. + // Fire onTransitionEnd immediately to match the scalar 'none' contract. + if (pendingBatchAnimationCount == 0) { + onTransitionEnd?.invoke(true) + } } else { // No initial animation — set target values directly (skip non-animated) if (mask and MASK_OPACITY != 0) this.alpha = opacity @@ -365,9 +371,15 @@ class EaseView(context: Context) : ReactViewGroup(context) { onTransitionEnd?.invoke(true) } else { // Subsequent updates: animate changed properties (skip non-animated) + var anyPropertyChanged = false + if (prevOpacity != null && mask and MASK_OPACITY != 0 && prevOpacity != opacity) { + anyPropertyChanged = true val config = getTransitionConfigForProperty(PROP_INDEX_OPACITY) if (config.type == "none") { + cancelSpringForProperty("alpha") + runningAnimators["alpha"]?.cancel() + runningAnimators.remove("alpha") this.alpha = opacity } else { val from = getCurrentValue("alpha") @@ -376,8 +388,12 @@ class EaseView(context: Context) : ReactViewGroup(context) { } if (prevTranslateX != null && mask and MASK_TRANSLATE_X != 0 && prevTranslateX != translateX) { + anyPropertyChanged = true val config = getTransitionConfigForProperty(PROP_INDEX_TRANSLATE_X) if (config.type == "none") { + cancelSpringForProperty("translationX") + runningAnimators["translationX"]?.cancel() + runningAnimators.remove("translationX") this.translationX = translateX } else { val from = getCurrentValue("translationX") @@ -386,8 +402,12 @@ class EaseView(context: Context) : ReactViewGroup(context) { } if (prevTranslateY != null && mask and MASK_TRANSLATE_Y != 0 && prevTranslateY != translateY) { + anyPropertyChanged = true val config = getTransitionConfigForProperty(PROP_INDEX_TRANSLATE_Y) if (config.type == "none") { + cancelSpringForProperty("translationY") + runningAnimators["translationY"]?.cancel() + runningAnimators.remove("translationY") this.translationY = translateY } else { val from = getCurrentValue("translationY") @@ -396,8 +416,12 @@ class EaseView(context: Context) : ReactViewGroup(context) { } if (prevScaleX != null && mask and MASK_SCALE_X != 0 && prevScaleX != scaleX) { + anyPropertyChanged = true val config = getTransitionConfigForProperty(PROP_INDEX_SCALE_X) if (config.type == "none") { + cancelSpringForProperty("scaleX") + runningAnimators["scaleX"]?.cancel() + runningAnimators.remove("scaleX") this.scaleX = scaleX } else { val from = getCurrentValue("scaleX") @@ -406,8 +430,12 @@ class EaseView(context: Context) : ReactViewGroup(context) { } if (prevScaleY != null && mask and MASK_SCALE_Y != 0 && prevScaleY != scaleY) { + anyPropertyChanged = true val config = getTransitionConfigForProperty(PROP_INDEX_SCALE_Y) if (config.type == "none") { + cancelSpringForProperty("scaleY") + runningAnimators["scaleY"]?.cancel() + runningAnimators.remove("scaleY") this.scaleY = scaleY } else { val from = getCurrentValue("scaleY") @@ -416,8 +444,12 @@ class EaseView(context: Context) : ReactViewGroup(context) { } if (prevRotate != null && mask and MASK_ROTATE != 0 && prevRotate != rotate) { + anyPropertyChanged = true val config = getTransitionConfigForProperty(PROP_INDEX_ROTATE) if (config.type == "none") { + cancelSpringForProperty("rotation") + runningAnimators["rotation"]?.cancel() + runningAnimators.remove("rotation") this.rotation = rotate } else { val from = getCurrentValue("rotation") @@ -426,8 +458,12 @@ class EaseView(context: Context) : ReactViewGroup(context) { } if (prevRotateX != null && mask and MASK_ROTATE_X != 0 && prevRotateX != rotateX) { + anyPropertyChanged = true val config = getTransitionConfigForProperty(PROP_INDEX_ROTATE_X) if (config.type == "none") { + cancelSpringForProperty("rotationX") + runningAnimators["rotationX"]?.cancel() + runningAnimators.remove("rotationX") this.rotationX = rotateX } else { val from = getCurrentValue("rotationX") @@ -436,8 +472,12 @@ class EaseView(context: Context) : ReactViewGroup(context) { } if (prevRotateY != null && mask and MASK_ROTATE_Y != 0 && prevRotateY != rotateY) { + anyPropertyChanged = true val config = getTransitionConfigForProperty(PROP_INDEX_ROTATE_Y) if (config.type == "none") { + cancelSpringForProperty("rotationY") + runningAnimators["rotationY"]?.cancel() + runningAnimators.remove("rotationY") this.rotationY = rotateY } else { val from = getCurrentValue("rotationY") @@ -446,8 +486,11 @@ class EaseView(context: Context) : ReactViewGroup(context) { } if (prevBorderRadius != null && mask and MASK_BORDER_RADIUS != 0 && prevBorderRadius != borderRadius) { + anyPropertyChanged = true val config = getTransitionConfigForProperty(PROP_INDEX_BORDER_RADIUS) if (config.type == "none") { + runningAnimators["animateBorderRadius"]?.cancel() + runningAnimators.remove("animateBorderRadius") setAnimateBorderRadius(borderRadius) } else { val from = getCurrentValue("animateBorderRadius") @@ -456,13 +499,22 @@ class EaseView(context: Context) : ReactViewGroup(context) { } if (prevBackgroundColor != null && mask and MASK_BACKGROUND_COLOR != 0 && prevBackgroundColor != backgroundColor) { + anyPropertyChanged = true val config = getTransitionConfigForProperty(PROP_INDEX_BACKGROUND_COLOR) if (config.type == "none") { + runningAnimators["backgroundColor"]?.cancel() + runningAnimators.remove("backgroundColor") applyBackgroundColor(backgroundColor) } else { animateBackgroundColor(getCurrentBackgroundColor(), backgroundColor, config) } } + + // If per-property arrays are populated and all changed properties resolved + // to 'none', no animations were queued. Fire onTransitionEnd immediately. + if (hasPerPropertyArrays() && anyPropertyChanged && pendingBatchAnimationCount == 0) { + onTransitionEnd?.invoke(true) + } } prevOpacity = opacity @@ -554,6 +606,17 @@ class EaseView(context: Context) : ReactViewGroup(context) { config: TransitionConfig, loop: Boolean = false ) { + if (config.type == "none") { + // Set immediately — cancel any running animation for this property + cancelSpringForProperty(propertyName) + runningAnimators[propertyName]?.cancel() + runningAnimators.remove(propertyName) + ObjectAnimator.ofFloat(this, propertyName, toValue).apply { + duration = 0 + start() + } + return + } if (config.type == "spring" && viewProperty != null) { animateSpring(viewProperty, toValue, config) } else { @@ -613,11 +676,13 @@ class EaseView(context: Context) : ReactViewGroup(context) { private fun animateSpring(viewProperty: DynamicAnimation.ViewProperty, toValue: Float, config: TransitionConfig) { cancelTimingForViewProperty(viewProperty) - val existingSpring = runningSpringAnimations[viewProperty] - if (existingSpring != null && existingSpring.isRunning) { - existingSpring.animateToFinalPosition(toValue) - return + // Cancel any existing spring so we get a fresh end listener with the current batchId. + runningSpringAnimations[viewProperty]?.let { existing -> + if (existing.isRunning) { + existing.cancel() + } } + runningSpringAnimations.remove(viewProperty) val batchId = animationBatchId pendingBatchAnimationCount++ diff --git a/ios/EaseView.mm b/ios/EaseView.mm index 753729e..37b83c9 100644 --- a/ios/EaseView.mm +++ b/ios/EaseView.mm @@ -414,41 +414,66 @@ - (void)updateProps:(const Props::Shared &)props newViewProps.initialAnimateBackgroundColor) .CGColor; - // Animate from initial to target + // Animate from initial to target (skip if config is 'none') if (hasInitialOpacity) { EaseTransitionConfig opacityConfig = transitionConfigForPropertyIndex(kPropIndexOpacity, newViewProps); self.layer.opacity = newViewProps.animateOpacity; - [self applyAnimationForKeyPath:@"opacity" - animationKey:kAnimKeyOpacity - fromValue:@(newViewProps.initialAnimateOpacity) - toValue:@(newViewProps.animateOpacity) - config:opacityConfig - loop:YES]; + if (opacityConfig.type != EaseViewTransitionType::None) { + [self applyAnimationForKeyPath:@"opacity" + animationKey:kAnimKeyOpacity + fromValue:@(newViewProps.initialAnimateOpacity) + toValue:@(newViewProps.animateOpacity) + config:opacityConfig + loop:YES]; + } } if (hasInitialTransform) { - int transformIdx = lowestTransformPropertyIndex(mask); + // Build mask of which transform sub-properties actually changed + int changedInitTransform = 0; + if (newViewProps.initialAnimateTranslateX != + newViewProps.animateTranslateX) + changedInitTransform |= kMaskTranslateX; + if (newViewProps.initialAnimateTranslateY != + newViewProps.animateTranslateY) + changedInitTransform |= kMaskTranslateY; + if (newViewProps.initialAnimateScaleX != newViewProps.animateScaleX) + changedInitTransform |= kMaskScaleX; + if (newViewProps.initialAnimateScaleY != newViewProps.animateScaleY) + changedInitTransform |= kMaskScaleY; + if (newViewProps.initialAnimateRotate != newViewProps.animateRotate) + changedInitTransform |= kMaskRotate; + if (newViewProps.initialAnimateRotateX != newViewProps.animateRotateX) + changedInitTransform |= kMaskRotateX; + if (newViewProps.initialAnimateRotateY != newViewProps.animateRotateY) + changedInitTransform |= kMaskRotateY; + int transformIdx = lowestTransformPropertyIndex(changedInitTransform); EaseTransitionConfig transformConfig = transitionConfigForPropertyIndex(transformIdx, newViewProps); self.layer.transform = targetT; - [self applyAnimationForKeyPath:@"transform" + if (transformConfig.type != EaseViewTransitionType::None) { + [self + applyAnimationForKeyPath:@"transform" animationKey:kAnimKeyTransform fromValue:[NSValue valueWithCATransform3D:initialT] toValue:[NSValue valueWithCATransform3D:targetT] config:transformConfig loop:YES]; + } } if (hasInitialBorderRadius) { EaseTransitionConfig brConfig = transitionConfigForPropertyIndex( kPropIndexBorderRadius, newViewProps); self.layer.cornerRadius = newViewProps.animateBorderRadius; - [self - applyAnimationForKeyPath:@"cornerRadius" - animationKey:kAnimKeyCornerRadius - fromValue:@(newViewProps.initialAnimateBorderRadius) - toValue:@(newViewProps.animateBorderRadius) - config:brConfig - loop:YES]; + if (brConfig.type != EaseViewTransitionType::None) { + [self applyAnimationForKeyPath:@"cornerRadius" + animationKey:kAnimKeyCornerRadius + fromValue:@(newViewProps + .initialAnimateBorderRadius) + toValue:@(newViewProps.animateBorderRadius) + config:brConfig + loop:YES]; + } } if (hasInitialBackgroundColor) { EaseTransitionConfig bgConfig = transitionConfigForPropertyIndex( @@ -456,7 +481,9 @@ - (void)updateProps:(const Props::Shared &)props self.layer.backgroundColor = RCTUIColorFromSharedColor(newViewProps.animateBackgroundColor) .CGColor; - [self applyAnimationForKeyPath:@"backgroundColor" + if (bgConfig.type != EaseViewTransitionType::None) { + [self + applyAnimationForKeyPath:@"backgroundColor" animationKey:kAnimKeyBackgroundColor fromValue:(__bridge id)RCTUIColorFromSharedColor( newViewProps @@ -467,6 +494,17 @@ - (void)updateProps:(const Props::Shared &)props .CGColor config:bgConfig loop:YES]; + } + } + + // If all per-property configs were 'none', no animations were queued. + // Fire onTransitionEnd immediately to match the scalar 'none' contract. + if (_pendingAnimationCount == 0 && _eventEmitter) { + auto emitter = + std::static_pointer_cast(_eventEmitter); + emitter->onTransitionEnd(EaseViewEventEmitter::OnTransitionEnd{ + .finished = true, + }); } } else { // No initial animation — set target values directly @@ -510,9 +548,11 @@ - (void)updateProps:(const Props::Shared &)props // Subsequent updates: animate changed properties const auto &oldViewProps = *std::static_pointer_cast(oldProps); + BOOL anyPropertyChanged = NO; if ((mask & kMaskOpacity) && oldViewProps.animateOpacity != newViewProps.animateOpacity) { + anyPropertyChanged = YES; EaseTransitionConfig opacityConfig = transitionConfigForPropertyIndex(kPropIndexOpacity, newViewProps); if (opacityConfig.type == EaseViewTransitionType::None) { @@ -543,6 +583,7 @@ - (void)updateProps:(const Props::Shared &)props oldViewProps.animateRotateY != newViewProps.animateRotateY; if (anyTransformChanged) { + anyPropertyChanged = YES; // Determine which transform sub-properties changed for config selection int changedTransformMask = 0; if (oldViewProps.animateTranslateX != newViewProps.animateTranslateX) @@ -583,6 +624,7 @@ - (void)updateProps:(const Props::Shared &)props if ((mask & kMaskBorderRadius) && oldViewProps.animateBorderRadius != newViewProps.animateBorderRadius) { + anyPropertyChanged = YES; EaseTransitionConfig brConfig = transitionConfigForPropertyIndex( kPropIndexBorderRadius, newViewProps); self.layer.cornerRadius = newViewProps.animateBorderRadius; @@ -603,6 +645,7 @@ - (void)updateProps:(const Props::Shared &)props if ((mask & kMaskBackgroundColor) && oldViewProps.animateBackgroundColor != newViewProps.animateBackgroundColor) { + anyPropertyChanged = YES; EaseTransitionConfig bgConfig = transitionConfigForPropertyIndex( kPropIndexBackgroundColor, newViewProps); CGColorRef toColor = @@ -622,6 +665,17 @@ - (void)updateProps:(const Props::Shared &)props loop:NO]; } } + + // If per-property arrays are populated and all changed properties resolved + // to 'none', no animations were queued. Fire onTransitionEnd immediately. + if (perProp && anyPropertyChanged && _pendingAnimationCount == 0 && + _eventEmitter) { + auto emitter = + std::static_pointer_cast(_eventEmitter); + emitter->onTransitionEnd(EaseViewEventEmitter::OnTransitionEnd{ + .finished = true, + }); + } } [CATransaction commit]; From ebc3676db4608b2be780650a3ec7bd1e1e51111b Mon Sep 17 00:00:00 2001 From: Janic Duplessis Date: Sun, 15 Mar 2026 21:20:20 -0400 Subject: [PATCH 3/6] fix: resolve rebase merge conflicts - fix duplicate vars, missing braces, delay prop --- android/src/main/java/com/ease/EaseViewManager.kt | 2 ++ ios/EaseView.mm | 5 +++-- src/EaseView.tsx | 15 +-------------- 3 files changed, 6 insertions(+), 16 deletions(-) diff --git a/android/src/main/java/com/ease/EaseViewManager.kt b/android/src/main/java/com/ease/EaseViewManager.kt index fa5aafc..4ae1bcd 100644 --- a/android/src/main/java/com/ease/EaseViewManager.kt +++ b/android/src/main/java/com/ease/EaseViewManager.kt @@ -176,6 +176,8 @@ class EaseViewManager : ReactViewManager() { @ReactProp(name = "transitionDelay", defaultInt = 0) fun setTransitionDelay(view: EaseView, value: Int) { view.transitionDelay = value.toLong() + } + // --- Per-property transition arrays --- @ReactProp(name = "perPropertyTransitionTypes") diff --git a/ios/EaseView.mm b/ios/EaseView.mm index 37b83c9..d9ea2c2 100644 --- a/ios/EaseView.mm +++ b/ios/EaseView.mm @@ -303,9 +303,10 @@ - (void)applyAnimationForKeyPath:(NSString *)keyPath toValue:toValue config:config loop:loop]; - if (props.transitionDelay > 0) { + const auto &easeProps = *std::static_pointer_cast(_props); + if (easeProps.transitionDelay > 0) { animation.beginTime = - CACurrentMediaTime() + (props.transitionDelay / 1000.0); + CACurrentMediaTime() + (easeProps.transitionDelay / 1000.0); animation.fillMode = kCAFillModeBackwards; } [animation setValue:@(_animationBatchId) forKey:@"easeBatchId"]; diff --git a/src/EaseView.tsx b/src/EaseView.tsx index a40789e..8f5f9ae 100644 --- a/src/EaseView.tsx +++ b/src/EaseView.tsx @@ -368,23 +368,11 @@ export function EaseView({ ? singleTransition.loop ?? 'none' : 'none'; } - const bezier: CubicBezier = Array.isArray(rawEasing) - ? rawEasing - : EASING_PRESETS[rawEasing]!; - const transitionDamping = - transition?.type === 'spring' ? transition.damping ?? 15 : 15; - const transitionStiffness = - transition?.type === 'spring' ? transition.stiffness ?? 120 : 120; - const transitionMass = - transition?.type === 'spring' ? transition.mass ?? 1 : 1; - const transitionLoop = - transition?.type === 'timing' ? transition.loop ?? 'none' : 'none'; const transitionDelay = transition?.type === 'timing' || transition?.type === 'spring' - ? transition.delay ?? 0 + ? (transition as any).delay ?? 0 : 0; - const handleTransitionEnd = onTransitionEnd ? (event: { nativeEvent: { finished: boolean } }) => onTransitionEnd(event.nativeEvent) @@ -430,7 +418,6 @@ export function EaseView({ perPropertyTransitionMasses={perPropertyArrays?.masses} perPropertyTransitionLoops={perPropertyArrays?.loops} perPropertyTransitionEasingBeziers={perPropertyArrays?.easingBeziers} - useHardwareLayer={useHardwareLayer} transformOriginX={transformOrigin?.x ?? 0.5} transformOriginY={transformOrigin?.y ?? 0.5} From 9cbf079e30bf4031811abf2c4fd4b5567677e4ce Mon Sep 17 00:00:00 2001 From: Janic Duplessis Date: Sun, 15 Mar 2026 21:40:13 -0400 Subject: [PATCH 4/6] fix: resolve type errors for TransitionMap union and clang-format --- ios/EaseView.mm | 3 ++- src/EaseView.tsx | 6 ++++-- src/EaseView.web.tsx | 25 +++++++++++++++++++------ 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/ios/EaseView.mm b/ios/EaseView.mm index d9ea2c2..ed1420a 100644 --- a/ios/EaseView.mm +++ b/ios/EaseView.mm @@ -303,7 +303,8 @@ - (void)applyAnimationForKeyPath:(NSString *)keyPath toValue:toValue config:config loop:loop]; - const auto &easeProps = *std::static_pointer_cast(_props); + const auto &easeProps = + *std::static_pointer_cast(_props); if (easeProps.transitionDelay > 0) { animation.beginTime = CACurrentMediaTime() + (easeProps.transitionDelay / 1000.0); diff --git a/src/EaseView.tsx b/src/EaseView.tsx index 8f5f9ae..ca0287f 100644 --- a/src/EaseView.tsx +++ b/src/EaseView.tsx @@ -368,9 +368,11 @@ export function EaseView({ ? singleTransition.loop ?? 'none' : 'none'; } + const singleTrans = + transition && 'type' in transition ? transition : undefined; const transitionDelay = - transition?.type === 'timing' || transition?.type === 'spring' - ? (transition as any).delay ?? 0 + singleTrans?.type === 'timing' || singleTrans?.type === 'spring' + ? singleTrans.delay ?? 0 : 0; const handleTransitionEnd = onTransitionEnd diff --git a/src/EaseView.web.tsx b/src/EaseView.web.tsx index a1e872b..c088785 100644 --- a/src/EaseView.web.tsx +++ b/src/EaseView.web.tsx @@ -3,6 +3,7 @@ import { View, type ViewStyle, type StyleProp } from 'react-native'; import type { AnimateProps, CubicBezier, + SingleTransition, Transition, TransitionEndEvent, TransformOrigin, @@ -81,7 +82,17 @@ function buildTransform(vals: ReturnType): string { return parts.length > 0 ? parts.join(' ') : 'none'; } -function resolveEasing(transition: Transition | undefined): string { +/** For web, resolve a Transition (which may be a TransitionMap) to a SingleTransition. */ +function resolveSingleTransition( + transition: Transition | undefined, +): SingleTransition | undefined { + if (!transition) return undefined; + if ('type' in transition) return transition as SingleTransition; + // TransitionMap — use the default config + return (transition as any).default as SingleTransition | undefined; +} + +function resolveEasing(transition: SingleTransition | undefined): string { if (!transition || transition.type !== 'timing') { return 'cubic-bezier(0.42, 0, 0.58, 1)'; } @@ -92,7 +103,7 @@ function resolveEasing(transition: Transition | undefined): string { return `cubic-bezier(${bezier[0]}, ${bezier[1]}, ${bezier[2]}, ${bezier[3]})`; } -function resolveDuration(transition: Transition | undefined): number { +function resolveDuration(transition: SingleTransition | undefined): number { if (!transition) return 300; if (transition.type === 'timing') return transition.duration ?? 300; if (transition.type === 'none') return 0; @@ -146,14 +157,16 @@ export function EaseView({ const displayValues = !mounted && hasInitial ? resolveAnimateValues(initialAnimate) : resolved; - const duration = resolveDuration(transition); - const easing = resolveEasing(transition); + const singleTransition = resolveSingleTransition(transition); + const duration = resolveDuration(singleTransition); + const easing = resolveEasing(singleTransition); const originX = ((transformOrigin?.x ?? 0.5) * 100).toFixed(1); const originY = ((transformOrigin?.y ?? 0.5) * 100).toFixed(1); - const transitionType = transition?.type ?? 'timing'; - const loopMode = transition?.type === 'timing' ? transition.loop : undefined; + const transitionType = singleTransition?.type ?? 'timing'; + const loopMode = + singleTransition?.type === 'timing' ? singleTransition.loop : undefined; const transitionCss = transitionType === 'none' || (!mounted && hasInitial) From 772755ea0e5e089d92ac6c5d7b47f6fe8527887f Mon Sep 17 00:00:00 2001 From: EQuimper Date: Mon, 16 Mar 2026 13:19:06 -0400 Subject: [PATCH 5/6] fix: changes how props is present --- android/src/main/java/com/ease/EaseView.kt | 184 +++++------ .../src/main/java/com/ease/EaseViewManager.kt | 120 +------ example/src/demos/index.ts | 6 +- ios/EaseView.mm | 232 ++++++------- src/EaseView.tsx | 306 +++++++++--------- src/EaseViewNativeComponent.ts | 57 ++-- src/__tests__/EaseView.test.tsx | 226 +++++++------ 7 files changed, 494 insertions(+), 637 deletions(-) diff --git a/android/src/main/java/com/ease/EaseView.kt b/android/src/main/java/com/ease/EaseView.kt index 1c4cf39..68635c4 100644 --- a/android/src/main/java/com/ease/EaseView.kt +++ b/android/src/main/java/com/ease/EaseView.kt @@ -13,6 +13,7 @@ import android.view.animation.PathInterpolator import androidx.dynamicanimation.animation.DynamicAnimation import androidx.dynamicanimation.animation.SpringAnimation import androidx.dynamicanimation.animation.SpringForce +import com.facebook.react.bridge.ReadableMap import com.facebook.react.views.view.ReactViewGroup import kotlin.math.sqrt @@ -34,24 +35,8 @@ class EaseView(context: Context) : ReactViewGroup(context) { // --- First mount tracking --- private var isFirstMount: Boolean = true - // --- Transition config (set by ViewManager) --- - var transitionType: String = "timing" - var transitionDuration: Int = 300 - var transitionEasingBezier: FloatArray = floatArrayOf(0.42f, 0f, 0.58f, 1.0f) - var transitionDamping: Float = 15.0f - var transitionStiffness: Float = 120.0f - var transitionMass: Float = 1.0f - var transitionLoop: String = "none" - var transitionDelay: Long = 0L - - // --- Per-property transition arrays (set by ViewManager) --- - var perPropertyTransitionTypes: Array? = null - var perPropertyTransitionDurations: IntArray? = null - var perPropertyTransitionDampings: FloatArray? = null - var perPropertyTransitionStiffnesses: FloatArray? = null - var perPropertyTransitionMasses: FloatArray? = null - var perPropertyTransitionLoops: Array? = null - var perPropertyTransitionEasingBeziers: FloatArray? = null + // --- Transition configs (set by ViewManager via ReadableMap) --- + private var transitionConfigs: Map = emptyMap() data class TransitionConfig( val type: String, @@ -60,49 +45,57 @@ class EaseView(context: Context) : ReactViewGroup(context) { val damping: Float, val stiffness: Float, val mass: Float, - val loop: String + val loop: String, + val delay: Long ) - fun getTransitionConfigForProperty(index: Int): TransitionConfig { - val types = perPropertyTransitionTypes - if (types != null && index < types.size) { - val durations = perPropertyTransitionDurations - val dampings = perPropertyTransitionDampings - val stiffnesses = perPropertyTransitionStiffnesses - val masses = perPropertyTransitionMasses - val loops = perPropertyTransitionLoops - val beziers = perPropertyTransitionEasingBeziers - - val bIdx = index * 4 - val bezier = if (beziers != null && bIdx + 3 < beziers.size) { - floatArrayOf(beziers[bIdx], beziers[bIdx + 1], beziers[bIdx + 2], beziers[bIdx + 3]) - } else { - floatArrayOf(0.42f, 0f, 0.58f, 1.0f) + fun setTransitionsFromMap(map: ReadableMap?) { + if (map == null) { + transitionConfigs = emptyMap() + return + } + val configs = mutableMapOf() + val keys = listOf("defaultConfig", "opacity", "translateX", "translateY", "scaleX", "scaleY", "rotate", "rotateX", "rotateY", "borderRadius", "backgroundColor") + for (key in keys) { + if (map.hasKey(key)) { + val configMap = map.getMap(key) ?: continue + val bezierArray = configMap.getArray("easingBezier") + val bezier = if (bezierArray != null && bezierArray.size() == 4) { + floatArrayOf( + bezierArray.getDouble(0).toFloat(), + bezierArray.getDouble(1).toFloat(), + bezierArray.getDouble(2).toFloat(), + bezierArray.getDouble(3).toFloat() + ) + } else { + floatArrayOf(0.42f, 0f, 0.58f, 1.0f) + } + configs[key] = TransitionConfig( + type = configMap.getString("type") ?: "timing", + duration = if (configMap.hasKey("duration")) configMap.getInt("duration") else 300, + easingBezier = bezier, + damping = if (configMap.hasKey("damping")) configMap.getDouble("damping").toFloat() else 15.0f, + stiffness = if (configMap.hasKey("stiffness")) configMap.getDouble("stiffness").toFloat() else 120.0f, + mass = if (configMap.hasKey("mass")) configMap.getDouble("mass").toFloat() else 1.0f, + loop = configMap.getString("loop") ?: "none", + delay = if (configMap.hasKey("delay")) configMap.getInt("delay").toLong() else 0L + ) } - - return TransitionConfig( - type = types[index], - duration = if (durations != null && index < durations.size) durations[index] else 300, - easingBezier = bezier, - damping = if (dampings != null && index < dampings.size) dampings[index] else 15.0f, - stiffness = if (stiffnesses != null && index < stiffnesses.size) stiffnesses[index] else 120.0f, - mass = if (masses != null && index < masses.size) masses[index] else 1.0f, - loop = if (loops != null && index < loops.size) loops[index] else "none" - ) } - // Fallback to scalar props - return TransitionConfig( - type = transitionType, - duration = transitionDuration, - easingBezier = transitionEasingBezier, - damping = transitionDamping, - stiffness = transitionStiffness, - mass = transitionMass, - loop = transitionLoop - ) + transitionConfigs = configs + } + + fun getTransitionConfig(name: String): TransitionConfig { + return transitionConfigs[name] + ?: transitionConfigs["defaultConfig"] + ?: TransitionConfig("timing", 300, floatArrayOf(0.42f, 0f, 0.58f, 1.0f), 15.0f, 120.0f, 1.0f, "none", 0L) + } + + private fun allTransitionsNone(): Boolean { + val keys = listOf("opacity", "translateX", "translateY", "scaleX", "scaleY", "rotate", "rotateX", "rotateY", "borderRadius", "backgroundColor") + return keys.all { getTransitionConfig(it).type == "none" } } - // Property indices matching JS constants companion object { // Bitmask flags — must match JS constants const val MASK_OPACITY = 1 shl 0 @@ -115,17 +108,6 @@ class EaseView(context: Context) : ReactViewGroup(context) { const val MASK_ROTATE_Y = 1 shl 7 const val MASK_BORDER_RADIUS = 1 shl 8 const val MASK_BACKGROUND_COLOR = 1 shl 9 - - const val PROP_INDEX_OPACITY = 0 - const val PROP_INDEX_TRANSLATE_X = 1 - const val PROP_INDEX_TRANSLATE_Y = 2 - const val PROP_INDEX_SCALE_X = 3 - const val PROP_INDEX_SCALE_Y = 4 - const val PROP_INDEX_ROTATE = 5 - const val PROP_INDEX_ROTATE_X = 6 - const val PROP_INDEX_ROTATE_Y = 7 - const val PROP_INDEX_BORDER_RADIUS = 8 - const val PROP_INDEX_BACKGROUND_COLOR = 9 } // --- Transform origin (0–1 fractions) --- @@ -202,8 +184,6 @@ class EaseView(context: Context) : ReactViewGroup(context) { // --- Animated properties bitmask (set by ViewManager) --- var animatedProperties: Int = 0 - private fun hasPerPropertyArrays(): Boolean = perPropertyTransitionTypes != null - init { // Set camera distance for 3D perspective rotations (rotateX/rotateY) cameraDistance = resources.displayMetrics.density * 850f @@ -307,34 +287,34 @@ class EaseView(context: Context) : ReactViewGroup(context) { // Animate properties that differ from initial to target if (mask and MASK_OPACITY != 0 && initialAnimateOpacity != opacity) { - animateProperty("alpha", DynamicAnimation.ALPHA, initialAnimateOpacity, opacity, getTransitionConfigForProperty(PROP_INDEX_OPACITY), loop = true) + animateProperty("alpha", DynamicAnimation.ALPHA, initialAnimateOpacity, opacity, getTransitionConfig("opacity"), loop = true) } if (mask and MASK_TRANSLATE_X != 0 && initialAnimateTranslateX != translateX) { - animateProperty("translationX", DynamicAnimation.TRANSLATION_X, initialAnimateTranslateX, translateX, getTransitionConfigForProperty(PROP_INDEX_TRANSLATE_X), loop = true) + animateProperty("translationX", DynamicAnimation.TRANSLATION_X, initialAnimateTranslateX, translateX, getTransitionConfig("translateX"), loop = true) } if (mask and MASK_TRANSLATE_Y != 0 && initialAnimateTranslateY != translateY) { - animateProperty("translationY", DynamicAnimation.TRANSLATION_Y, initialAnimateTranslateY, translateY, getTransitionConfigForProperty(PROP_INDEX_TRANSLATE_Y), loop = true) + animateProperty("translationY", DynamicAnimation.TRANSLATION_Y, initialAnimateTranslateY, translateY, getTransitionConfig("translateY"), loop = true) } if (mask and MASK_SCALE_X != 0 && initialAnimateScaleX != scaleX) { - animateProperty("scaleX", DynamicAnimation.SCALE_X, initialAnimateScaleX, scaleX, getTransitionConfigForProperty(PROP_INDEX_SCALE_X), loop = true) + animateProperty("scaleX", DynamicAnimation.SCALE_X, initialAnimateScaleX, scaleX, getTransitionConfig("scaleX"), loop = true) } if (mask and MASK_SCALE_Y != 0 && initialAnimateScaleY != scaleY) { - animateProperty("scaleY", DynamicAnimation.SCALE_Y, initialAnimateScaleY, scaleY, getTransitionConfigForProperty(PROP_INDEX_SCALE_Y), loop = true) + animateProperty("scaleY", DynamicAnimation.SCALE_Y, initialAnimateScaleY, scaleY, getTransitionConfig("scaleY"), loop = true) } if (mask and MASK_ROTATE != 0 && initialAnimateRotate != rotate) { - animateProperty("rotation", DynamicAnimation.ROTATION, initialAnimateRotate, rotate, getTransitionConfigForProperty(PROP_INDEX_ROTATE), loop = true) + animateProperty("rotation", DynamicAnimation.ROTATION, initialAnimateRotate, rotate, getTransitionConfig("rotate"), loop = true) } if (mask and MASK_ROTATE_X != 0 && initialAnimateRotateX != rotateX) { - animateProperty("rotationX", DynamicAnimation.ROTATION_X, initialAnimateRotateX, rotateX, getTransitionConfigForProperty(PROP_INDEX_ROTATE_X), loop = true) + animateProperty("rotationX", DynamicAnimation.ROTATION_X, initialAnimateRotateX, rotateX, getTransitionConfig("rotateX"), loop = true) } if (mask and MASK_ROTATE_Y != 0 && initialAnimateRotateY != rotateY) { - animateProperty("rotationY", DynamicAnimation.ROTATION_Y, initialAnimateRotateY, rotateY, getTransitionConfigForProperty(PROP_INDEX_ROTATE_Y), loop = true) + animateProperty("rotationY", DynamicAnimation.ROTATION_Y, initialAnimateRotateY, rotateY, getTransitionConfig("rotateY"), loop = true) } if (mask and MASK_BORDER_RADIUS != 0 && initialAnimateBorderRadius != borderRadius) { - animateProperty("animateBorderRadius", null, initialAnimateBorderRadius, borderRadius, getTransitionConfigForProperty(PROP_INDEX_BORDER_RADIUS), loop = true) + animateProperty("animateBorderRadius", null, initialAnimateBorderRadius, borderRadius, getTransitionConfig("borderRadius"), loop = true) } if (mask and MASK_BACKGROUND_COLOR != 0 && initialAnimateBackgroundColor != backgroundColor) { - animateBackgroundColor(initialAnimateBackgroundColor, backgroundColor, getTransitionConfigForProperty(PROP_INDEX_BACKGROUND_COLOR), loop = true) + animateBackgroundColor(initialAnimateBackgroundColor, backgroundColor, getTransitionConfig("backgroundColor"), loop = true) } // If all per-property configs were 'none', no animations were queued. @@ -355,7 +335,7 @@ class EaseView(context: Context) : ReactViewGroup(context) { if (mask and MASK_BORDER_RADIUS != 0) setAnimateBorderRadius(borderRadius) if (mask and MASK_BACKGROUND_COLOR != 0) applyBackgroundColor(backgroundColor) } - } else if (!hasPerPropertyArrays() && transitionType == "none") { + } else if (allTransitionsNone()) { // No transition (scalar) — set values immediately, cancel running animations cancelAllAnimations() if (mask and MASK_OPACITY != 0) this.alpha = opacity @@ -375,7 +355,7 @@ class EaseView(context: Context) : ReactViewGroup(context) { if (prevOpacity != null && mask and MASK_OPACITY != 0 && prevOpacity != opacity) { anyPropertyChanged = true - val config = getTransitionConfigForProperty(PROP_INDEX_OPACITY) + val config = getTransitionConfig("opacity") if (config.type == "none") { cancelSpringForProperty("alpha") runningAnimators["alpha"]?.cancel() @@ -389,7 +369,7 @@ class EaseView(context: Context) : ReactViewGroup(context) { if (prevTranslateX != null && mask and MASK_TRANSLATE_X != 0 && prevTranslateX != translateX) { anyPropertyChanged = true - val config = getTransitionConfigForProperty(PROP_INDEX_TRANSLATE_X) + val config = getTransitionConfig("translateX") if (config.type == "none") { cancelSpringForProperty("translationX") runningAnimators["translationX"]?.cancel() @@ -403,7 +383,7 @@ class EaseView(context: Context) : ReactViewGroup(context) { if (prevTranslateY != null && mask and MASK_TRANSLATE_Y != 0 && prevTranslateY != translateY) { anyPropertyChanged = true - val config = getTransitionConfigForProperty(PROP_INDEX_TRANSLATE_Y) + val config = getTransitionConfig("translateY") if (config.type == "none") { cancelSpringForProperty("translationY") runningAnimators["translationY"]?.cancel() @@ -417,7 +397,7 @@ class EaseView(context: Context) : ReactViewGroup(context) { if (prevScaleX != null && mask and MASK_SCALE_X != 0 && prevScaleX != scaleX) { anyPropertyChanged = true - val config = getTransitionConfigForProperty(PROP_INDEX_SCALE_X) + val config = getTransitionConfig("scaleX") if (config.type == "none") { cancelSpringForProperty("scaleX") runningAnimators["scaleX"]?.cancel() @@ -431,7 +411,7 @@ class EaseView(context: Context) : ReactViewGroup(context) { if (prevScaleY != null && mask and MASK_SCALE_Y != 0 && prevScaleY != scaleY) { anyPropertyChanged = true - val config = getTransitionConfigForProperty(PROP_INDEX_SCALE_Y) + val config = getTransitionConfig("scaleY") if (config.type == "none") { cancelSpringForProperty("scaleY") runningAnimators["scaleY"]?.cancel() @@ -445,7 +425,7 @@ class EaseView(context: Context) : ReactViewGroup(context) { if (prevRotate != null && mask and MASK_ROTATE != 0 && prevRotate != rotate) { anyPropertyChanged = true - val config = getTransitionConfigForProperty(PROP_INDEX_ROTATE) + val config = getTransitionConfig("rotate") if (config.type == "none") { cancelSpringForProperty("rotation") runningAnimators["rotation"]?.cancel() @@ -459,7 +439,7 @@ class EaseView(context: Context) : ReactViewGroup(context) { if (prevRotateX != null && mask and MASK_ROTATE_X != 0 && prevRotateX != rotateX) { anyPropertyChanged = true - val config = getTransitionConfigForProperty(PROP_INDEX_ROTATE_X) + val config = getTransitionConfig("rotateX") if (config.type == "none") { cancelSpringForProperty("rotationX") runningAnimators["rotationX"]?.cancel() @@ -473,7 +453,7 @@ class EaseView(context: Context) : ReactViewGroup(context) { if (prevRotateY != null && mask and MASK_ROTATE_Y != 0 && prevRotateY != rotateY) { anyPropertyChanged = true - val config = getTransitionConfigForProperty(PROP_INDEX_ROTATE_Y) + val config = getTransitionConfig("rotateY") if (config.type == "none") { cancelSpringForProperty("rotationY") runningAnimators["rotationY"]?.cancel() @@ -487,7 +467,7 @@ class EaseView(context: Context) : ReactViewGroup(context) { if (prevBorderRadius != null && mask and MASK_BORDER_RADIUS != 0 && prevBorderRadius != borderRadius) { anyPropertyChanged = true - val config = getTransitionConfigForProperty(PROP_INDEX_BORDER_RADIUS) + val config = getTransitionConfig("borderRadius") if (config.type == "none") { runningAnimators["animateBorderRadius"]?.cancel() runningAnimators.remove("animateBorderRadius") @@ -500,7 +480,7 @@ class EaseView(context: Context) : ReactViewGroup(context) { if (prevBackgroundColor != null && mask and MASK_BACKGROUND_COLOR != 0 && prevBackgroundColor != backgroundColor) { anyPropertyChanged = true - val config = getTransitionConfigForProperty(PROP_INDEX_BACKGROUND_COLOR) + val config = getTransitionConfig("backgroundColor") if (config.type == "none") { runningAnimators["backgroundColor"]?.cancel() runningAnimators.remove("backgroundColor") @@ -510,9 +490,9 @@ class EaseView(context: Context) : ReactViewGroup(context) { } } - // If per-property arrays are populated and all changed properties resolved - // to 'none', no animations were queued. Fire onTransitionEnd immediately. - if (hasPerPropertyArrays() && anyPropertyChanged && pendingBatchAnimationCount == 0) { + // If all changed properties resolved to 'none', no animations were queued. + // Fire onTransitionEnd immediately. + if (anyPropertyChanged && pendingBatchAnimationCount == 0) { onTransitionEnd?.invoke(true) } } @@ -558,9 +538,8 @@ class EaseView(context: Context) : ReactViewGroup(context) { pendingBatchAnimationCount++ val animator = ValueAnimator.ofArgb(fromColor, toColor).apply { - duration = transitionDuration.toLong() - startDelay = transitionDelay duration = config.duration.toLong() + startDelay = config.delay interpolator = PathInterpolator( config.easingBezier[0], config.easingBezier[1], @@ -632,9 +611,8 @@ class EaseView(context: Context) : ReactViewGroup(context) { pendingBatchAnimationCount++ val animator = ObjectAnimator.ofFloat(this, propertyName, fromValue, toValue).apply { - duration = transitionDuration.toLong() - startDelay = transitionDelay duration = config.duration.toLong() + startDelay = config.delay interpolator = PathInterpolator( config.easingBezier[0], config.easingBezier[1], @@ -715,10 +693,10 @@ class EaseView(context: Context) : ReactViewGroup(context) { onEaseAnimationStart() runningSpringAnimations[viewProperty] = spring - if (transitionDelay > 0) { + if (config.delay > 0) { val runnable = Runnable { spring.start() } pendingDelayedRunnables.add(runnable) - postDelayed(runnable, transitionDelay) + postDelayed(runnable, config.delay) } else { spring.start() } @@ -822,14 +800,6 @@ class EaseView(context: Context) : ReactViewGroup(context) { applyBackgroundColor(Color.TRANSPARENT) isFirstMount = true - transitionLoop = "none" - - perPropertyTransitionTypes = null - perPropertyTransitionDurations = null - perPropertyTransitionDampings = null - perPropertyTransitionStiffnesses = null - perPropertyTransitionMasses = null - perPropertyTransitionLoops = null - perPropertyTransitionEasingBeziers = null + transitionConfigs = emptyMap() } } diff --git a/android/src/main/java/com/ease/EaseViewManager.kt b/android/src/main/java/com/ease/EaseViewManager.kt index 4ae1bcd..4282310 100644 --- a/android/src/main/java/com/ease/EaseViewManager.kt +++ b/android/src/main/java/com/ease/EaseViewManager.kt @@ -3,6 +3,7 @@ package com.ease import android.graphics.Color import com.facebook.react.bridge.Arguments import com.facebook.react.bridge.ReadableArray +import com.facebook.react.bridge.ReadableMap import com.facebook.react.bridge.WritableMap import com.facebook.react.module.annotations.ReactModule import com.facebook.react.uimanager.PixelUtil @@ -126,122 +127,11 @@ class EaseViewManager : ReactViewManager() { view.initialAnimateBorderRadius = PixelUtil.toPixelFromDIP(value) } - // --- Transition config setters --- - - @ReactProp(name = "transitionType") - fun setTransitionType(view: EaseView, value: String?) { - view.transitionType = value ?: "timing" - } - - @ReactProp(name = "transitionDuration", defaultInt = 300) - fun setTransitionDuration(view: EaseView, value: Int) { - view.transitionDuration = value - } - - @ReactProp(name = "transitionEasingBezier") - fun setTransitionEasingBezier(view: EaseView, value: ReadableArray?) { - if (value != null && value.size() == 4) { - view.transitionEasingBezier = floatArrayOf( - value.getDouble(0).toFloat(), - value.getDouble(1).toFloat(), - value.getDouble(2).toFloat(), - value.getDouble(3).toFloat() - ) - } else { - // Fallback: easeInOut - view.transitionEasingBezier = floatArrayOf(0.42f, 0f, 0.58f, 1.0f) - } - } - - @ReactProp(name = "transitionDamping", defaultFloat = 15f) - fun setTransitionDamping(view: EaseView, value: Float) { - view.transitionDamping = value - } - - @ReactProp(name = "transitionStiffness", defaultFloat = 120f) - fun setTransitionStiffness(view: EaseView, value: Float) { - view.transitionStiffness = value - } - - @ReactProp(name = "transitionMass", defaultFloat = 1f) - fun setTransitionMass(view: EaseView, value: Float) { - view.transitionMass = value - } - - @ReactProp(name = "transitionLoop") - fun setTransitionLoop(view: EaseView, value: String?) { - view.transitionLoop = value ?: "none" - } - - @ReactProp(name = "transitionDelay", defaultInt = 0) - fun setTransitionDelay(view: EaseView, value: Int) { - view.transitionDelay = value.toLong() - } - - // --- Per-property transition arrays --- - - @ReactProp(name = "perPropertyTransitionTypes") - fun setPerPropertyTransitionTypes(view: EaseView, value: ReadableArray?) { - if (value != null && value.size() == 10) { - view.perPropertyTransitionTypes = Array(10) { value.getString(it) ?: "" } - } else { - view.perPropertyTransitionTypes = null - } - } - - @ReactProp(name = "perPropertyTransitionDurations") - fun setPerPropertyTransitionDurations(view: EaseView, value: ReadableArray?) { - if (value != null && value.size() == 10) { - view.perPropertyTransitionDurations = IntArray(10) { value.getInt(it) } - } else { - view.perPropertyTransitionDurations = null - } - } - - @ReactProp(name = "perPropertyTransitionDampings") - fun setPerPropertyTransitionDampings(view: EaseView, value: ReadableArray?) { - if (value != null && value.size() == 10) { - view.perPropertyTransitionDampings = FloatArray(10) { value.getDouble(it).toFloat() } - } else { - view.perPropertyTransitionDampings = null - } - } - - @ReactProp(name = "perPropertyTransitionStiffnesses") - fun setPerPropertyTransitionStiffnesses(view: EaseView, value: ReadableArray?) { - if (value != null && value.size() == 10) { - view.perPropertyTransitionStiffnesses = FloatArray(10) { value.getDouble(it).toFloat() } - } else { - view.perPropertyTransitionStiffnesses = null - } - } - - @ReactProp(name = "perPropertyTransitionMasses") - fun setPerPropertyTransitionMasses(view: EaseView, value: ReadableArray?) { - if (value != null && value.size() == 10) { - view.perPropertyTransitionMasses = FloatArray(10) { value.getDouble(it).toFloat() } - } else { - view.perPropertyTransitionMasses = null - } - } - - @ReactProp(name = "perPropertyTransitionLoops") - fun setPerPropertyTransitionLoops(view: EaseView, value: ReadableArray?) { - if (value != null && value.size() == 10) { - view.perPropertyTransitionLoops = Array(10) { value.getString(it) ?: "" } - } else { - view.perPropertyTransitionLoops = null - } - } - - @ReactProp(name = "perPropertyTransitionEasingBeziers") - fun setPerPropertyTransitionEasingBeziers(view: EaseView, value: ReadableArray?) { - if (value != null && value.size() == 40) { - view.perPropertyTransitionEasingBeziers = FloatArray(40) { value.getDouble(it).toFloat() } - } else { - view.perPropertyTransitionEasingBeziers = null - } + // --- Transitions config (single ReadableMap) --- + @ReactProp(name = "transitions") + fun setTransitions(view: EaseView, value: ReadableMap?) { + view.setTransitionsFromMap(value) } // --- Border radius --- diff --git a/example/src/demos/index.ts b/example/src/demos/index.ts index 4f35bfd..9f39566 100644 --- a/example/src/demos/index.ts +++ b/example/src/demos/index.ts @@ -36,7 +36,6 @@ export const demos: Record = { 'rotate': { component: RotateDemo, title: 'Rotate', section: 'Transform' }, 'scale': { component: ScaleDemo, title: 'Scale', section: 'Transform' }, 'transform-origin': { - 'per-property': { component: PerPropertyDemo, title: 'Per-Property', section: 'Advanced' }, component: TransformOriginDemo, title: 'Transform Origin', section: 'Transform', @@ -80,6 +79,11 @@ export const demos: Record = { title: 'Comparison', section: 'Advanced', }, + 'per-property': { + component: PerPropertyDemo, + title: 'Per-Property', + section: 'Advanced', + }, }; interface SectionData { diff --git a/ios/EaseView.mm b/ios/EaseView.mm index ed1420a..b4eea9f 100644 --- a/ios/EaseView.mm +++ b/ios/EaseView.mm @@ -58,79 +58,26 @@ static CATransform3D composeTransform(CGFloat scaleX, CGFloat scaleY, kMaskScaleX | kMaskScaleY | kMaskRotate | kMaskRotateX | kMaskRotateY; -// Per-property transition config resolved from arrays or scalar fallback +// Per-property transition config resolved from the transitions struct struct EaseTransitionConfig { - EaseViewTransitionType type; + std::string type; int duration; float bezier[4]; float damping; float stiffness; float mass; - EaseViewTransitionLoop loop; + std::string loop; + int delay; }; -static EaseTransitionConfig -transitionConfigForPropertyIndex(int index, const EaseViewProps &props) { - const auto &types = props.perPropertyTransitionTypes; - if (!types.empty() && index < (int)types.size()) { - EaseTransitionConfig config; - // Type - const auto &typeStr = types[index]; - if (typeStr == "spring") { - config.type = EaseViewTransitionType::Spring; - } else if (typeStr == "none") { - config.type = EaseViewTransitionType::None; - } else { - config.type = EaseViewTransitionType::Timing; - } - // Duration - const auto &durations = props.perPropertyTransitionDurations; - config.duration = (index < (int)durations.size()) ? durations[index] : 300; - // Bezier (4 values per property) - const auto &beziers = props.perPropertyTransitionEasingBeziers; - int bIdx = index * 4; - if (bIdx + 3 < (int)beziers.size()) { - config.bezier[0] = beziers[bIdx]; - config.bezier[1] = beziers[bIdx + 1]; - config.bezier[2] = beziers[bIdx + 2]; - config.bezier[3] = beziers[bIdx + 3]; - } else { - config.bezier[0] = 0.42f; - config.bezier[1] = 0.0f; - config.bezier[2] = 0.58f; - config.bezier[3] = 1.0f; - } - // Damping - const auto &dampings = props.perPropertyTransitionDampings; - config.damping = (index < (int)dampings.size()) ? dampings[index] : 15.0f; - // Stiffness - const auto &stiffnesses = props.perPropertyTransitionStiffnesses; - config.stiffness = - (index < (int)stiffnesses.size()) ? stiffnesses[index] : 120.0f; - // Mass - const auto &masses = props.perPropertyTransitionMasses; - config.mass = (index < (int)masses.size()) ? masses[index] : 1.0f; - // Loop - const auto &loops = props.perPropertyTransitionLoops; - if (index < (int)loops.size()) { - const auto &loopStr = loops[index]; - if (loopStr == "repeat") { - config.loop = EaseViewTransitionLoop::Repeat; - } else if (loopStr == "reverse") { - config.loop = EaseViewTransitionLoop::Reverse; - } else { - config.loop = EaseViewTransitionLoop::None; - } - } else { - config.loop = EaseViewTransitionLoop::None; - } - return config; - } - // Fallback to scalar props +// Convert from a codegen-generated transition config struct to our local +// EaseTransitionConfig +template +static EaseTransitionConfig transitionConfigFromStruct(const T &src) { EaseTransitionConfig config; - config.type = props.transitionType; - config.duration = props.transitionDuration; - const auto &b = props.transitionEasingBezier; + config.type = src.type; + config.duration = src.duration; + const auto &b = src.easingBezier; if (b.size() == 4) { config.bezier[0] = b[0]; config.bezier[1] = b[1]; @@ -142,38 +89,59 @@ static CATransform3D composeTransform(CGFloat scaleX, CGFloat scaleY, config.bezier[2] = 0.58f; config.bezier[3] = 1.0f; } - config.damping = props.transitionDamping; - config.stiffness = props.transitionStiffness; - config.mass = props.transitionMass; - config.loop = props.transitionLoop; + config.damping = src.damping; + config.stiffness = src.stiffness; + config.mass = src.mass; + config.loop = src.loop; + config.delay = src.delay; return config; } -// Property indices matching JS constants -static const int kPropIndexOpacity = 0; -static const int kPropIndexTranslateX = 1; -// static const int kPropIndexTranslateY = 2; -// static const int kPropIndexScaleX = 3; -// static const int kPropIndexScaleY = 4; -// static const int kPropIndexRotate = 5; -// static const int kPropIndexRotateX = 6; -// static const int kPropIndexRotateY = 7; -static const int kPropIndexBorderRadius = 8; -static const int kPropIndexBackgroundColor = 9; - -// Check if per-property arrays are populated -static BOOL hasPerPropertyArrays(const EaseViewProps &props) { - return !props.perPropertyTransitionTypes.empty(); +static EaseTransitionConfig +transitionConfigForProperty(const std::string &name, + const EaseViewProps &props) { + if (name == "opacity") { + return transitionConfigFromStruct(props.transitions.opacity); + } else if (name == "translateX") { + return transitionConfigFromStruct(props.transitions.translateX); + } else if (name == "translateY") { + return transitionConfigFromStruct(props.transitions.translateY); + } else if (name == "scaleX") { + return transitionConfigFromStruct(props.transitions.scaleX); + } else if (name == "scaleY") { + return transitionConfigFromStruct(props.transitions.scaleY); + } else if (name == "rotate") { + return transitionConfigFromStruct(props.transitions.rotate); + } else if (name == "rotateX") { + return transitionConfigFromStruct(props.transitions.rotateX); + } else if (name == "rotateY") { + return transitionConfigFromStruct(props.transitions.rotateY); + } else if (name == "borderRadius") { + return transitionConfigFromStruct(props.transitions.borderRadius); + } else if (name == "backgroundColor") { + return transitionConfigFromStruct(props.transitions.backgroundColor); + } + // Fallback to defaultConfig + return transitionConfigFromStruct(props.transitions.defaultConfig); } -// Find lowest property index with a set mask bit among transform properties -static int lowestTransformPropertyIndex(int mask) { - for (int i = 1; i <= 7; i++) { - if (mask & (1 << i)) { - return i; - } - } - return 1; // fallback to translateX +// Find lowest property name with a set mask bit among transform properties +static std::string lowestTransformPropertyName(int mask) { + if (mask & kMaskTranslateX) + return "translateX"; + if (mask & kMaskTranslateY) + return "translateY"; + if (mask & kMaskScaleX) + return "scaleX"; + if (mask & kMaskScaleY) + return "scaleY"; + if (mask & kMaskRotate) + return "rotate"; + if (mask & kMaskRotateX) + return "rotateX"; + if (mask & kMaskRotateY) + return "rotateY"; + return "translateX"; // fallback } @implementation EaseView { @@ -259,7 +227,7 @@ - (CAAnimation *)createAnimationForKeyPath:(NSString *)keyPath toValue:(NSValue *)toValue config:(EaseTransitionConfig)config loop:(BOOL)loop { - if (config.type == EaseViewTransitionType::Spring) { + if (config.type == "spring") { CASpringAnimation *spring = [CASpringAnimation animationWithKeyPath:keyPath]; spring.fromValue = fromValue; @@ -279,9 +247,9 @@ - (CAAnimation *)createAnimationForKeyPath:(NSString *)keyPath functionWithControlPoints:config.bezier[0]:config.bezier[1 ]:config.bezier[2]:config.bezier[3]]; if (loop) { - if (config.loop == EaseViewTransitionLoop::Repeat) { + if (config.loop == "repeat") { timing.repeatCount = HUGE_VALF; - } else if (config.loop == EaseViewTransitionLoop::Reverse) { + } else if (config.loop == "reverse") { timing.repeatCount = HUGE_VALF; timing.autoreverses = YES; } @@ -303,11 +271,8 @@ - (void)applyAnimationForKeyPath:(NSString *)keyPath toValue:toValue config:config loop:loop]; - const auto &easeProps = - *std::static_pointer_cast(_props); - if (easeProps.transitionDelay > 0) { - animation.beginTime = - CACurrentMediaTime() + (easeProps.transitionDelay / 1000.0); + if (config.delay > 0) { + animation.beginTime = CACurrentMediaTime() + (config.delay / 1000.0); animation.fillMode = kCAFillModeBackwards; } [animation setValue:@(_animationBatchId) forKey:@"easeBatchId"]; @@ -368,8 +333,6 @@ - (void)updateProps:(const Props::Shared &)props int mask = newViewProps.animatedProperties; BOOL hasTransform = (mask & kMaskAnyTransform) != 0; - BOOL perProp = hasPerPropertyArrays(newViewProps); - if (_isFirstMount) { _isFirstMount = NO; @@ -419,9 +382,9 @@ - (void)updateProps:(const Props::Shared &)props // Animate from initial to target (skip if config is 'none') if (hasInitialOpacity) { EaseTransitionConfig opacityConfig = - transitionConfigForPropertyIndex(kPropIndexOpacity, newViewProps); + transitionConfigForProperty("opacity", newViewProps); self.layer.opacity = newViewProps.animateOpacity; - if (opacityConfig.type != EaseViewTransitionType::None) { + if (opacityConfig.type != "none") { [self applyAnimationForKeyPath:@"opacity" animationKey:kAnimKeyOpacity fromValue:@(newViewProps.initialAnimateOpacity) @@ -449,11 +412,12 @@ - (void)updateProps:(const Props::Shared &)props changedInitTransform |= kMaskRotateX; if (newViewProps.initialAnimateRotateY != newViewProps.animateRotateY) changedInitTransform |= kMaskRotateY; - int transformIdx = lowestTransformPropertyIndex(changedInitTransform); + std::string transformName = + lowestTransformPropertyName(changedInitTransform); EaseTransitionConfig transformConfig = - transitionConfigForPropertyIndex(transformIdx, newViewProps); + transitionConfigForProperty(transformName, newViewProps); self.layer.transform = targetT; - if (transformConfig.type != EaseViewTransitionType::None) { + if (transformConfig.type != "none") { [self applyAnimationForKeyPath:@"transform" animationKey:kAnimKeyTransform @@ -464,10 +428,10 @@ - (void)updateProps:(const Props::Shared &)props } } if (hasInitialBorderRadius) { - EaseTransitionConfig brConfig = transitionConfigForPropertyIndex( - kPropIndexBorderRadius, newViewProps); + EaseTransitionConfig brConfig = + transitionConfigForProperty("borderRadius", newViewProps); self.layer.cornerRadius = newViewProps.animateBorderRadius; - if (brConfig.type != EaseViewTransitionType::None) { + if (brConfig.type != "none") { [self applyAnimationForKeyPath:@"cornerRadius" animationKey:kAnimKeyCornerRadius fromValue:@(newViewProps @@ -478,12 +442,12 @@ - (void)updateProps:(const Props::Shared &)props } } if (hasInitialBackgroundColor) { - EaseTransitionConfig bgConfig = transitionConfigForPropertyIndex( - kPropIndexBackgroundColor, newViewProps); + EaseTransitionConfig bgConfig = + transitionConfigForProperty("backgroundColor", newViewProps); self.layer.backgroundColor = RCTUIColorFromSharedColor(newViewProps.animateBackgroundColor) .CGColor; - if (bgConfig.type != EaseViewTransitionType::None) { + if (bgConfig.type != "none") { [self applyAnimationForKeyPath:@"backgroundColor" animationKey:kAnimKeyBackgroundColor @@ -523,9 +487,17 @@ - (void)updateProps:(const Props::Shared &)props RCTUIColorFromSharedColor(newViewProps.animateBackgroundColor) .CGColor; } - } else if (!perProp && - newViewProps.transitionType == EaseViewTransitionType::None) { - // No transition (scalar) — set values immediately + } else if (newViewProps.transitions.opacity.type == "none" && + newViewProps.transitions.translateX.type == "none" && + newViewProps.transitions.translateY.type == "none" && + newViewProps.transitions.scaleX.type == "none" && + newViewProps.transitions.scaleY.type == "none" && + newViewProps.transitions.rotate.type == "none" && + newViewProps.transitions.rotateX.type == "none" && + newViewProps.transitions.rotateY.type == "none" && + newViewProps.transitions.borderRadius.type == "none" && + newViewProps.transitions.backgroundColor.type == "none") { + // All transitions are 'none' — set values immediately [self.layer removeAllAnimations]; if (mask & kMaskOpacity) self.layer.opacity = newViewProps.animateOpacity; @@ -556,8 +528,8 @@ - (void)updateProps:(const Props::Shared &)props oldViewProps.animateOpacity != newViewProps.animateOpacity) { anyPropertyChanged = YES; EaseTransitionConfig opacityConfig = - transitionConfigForPropertyIndex(kPropIndexOpacity, newViewProps); - if (opacityConfig.type == EaseViewTransitionType::None) { + transitionConfigForProperty("opacity", newViewProps); + if (opacityConfig.type == "none") { self.layer.opacity = newViewProps.animateOpacity; [self.layer removeAnimationForKey:kAnimKeyOpacity]; } else { @@ -603,11 +575,12 @@ - (void)updateProps:(const Props::Shared &)props if (oldViewProps.animateRotateY != newViewProps.animateRotateY) changedTransformMask |= kMaskRotateY; - int transformIdx = lowestTransformPropertyIndex(changedTransformMask); + std::string transformName = + lowestTransformPropertyName(changedTransformMask); EaseTransitionConfig transformConfig = - transitionConfigForPropertyIndex(transformIdx, newViewProps); + transitionConfigForProperty(transformName, newViewProps); - if (transformConfig.type == EaseViewTransitionType::None) { + if (transformConfig.type == "none") { self.layer.transform = [self targetTransformFromProps:newViewProps]; [self.layer removeAnimationForKey:kAnimKeyTransform]; } else { @@ -627,11 +600,11 @@ - (void)updateProps:(const Props::Shared &)props if ((mask & kMaskBorderRadius) && oldViewProps.animateBorderRadius != newViewProps.animateBorderRadius) { anyPropertyChanged = YES; - EaseTransitionConfig brConfig = transitionConfigForPropertyIndex( - kPropIndexBorderRadius, newViewProps); + EaseTransitionConfig brConfig = + transitionConfigForProperty("borderRadius", newViewProps); self.layer.cornerRadius = newViewProps.animateBorderRadius; self.layer.masksToBounds = newViewProps.animateBorderRadius > 0; - if (brConfig.type == EaseViewTransitionType::None) { + if (brConfig.type == "none") { [self.layer removeAnimationForKey:kAnimKeyCornerRadius]; } else { [self applyAnimationForKeyPath:@"cornerRadius" @@ -648,13 +621,13 @@ - (void)updateProps:(const Props::Shared &)props oldViewProps.animateBackgroundColor != newViewProps.animateBackgroundColor) { anyPropertyChanged = YES; - EaseTransitionConfig bgConfig = transitionConfigForPropertyIndex( - kPropIndexBackgroundColor, newViewProps); + EaseTransitionConfig bgConfig = + transitionConfigForProperty("backgroundColor", newViewProps); CGColorRef toColor = RCTUIColorFromSharedColor(newViewProps.animateBackgroundColor) .CGColor; self.layer.backgroundColor = toColor; - if (bgConfig.type == EaseViewTransitionType::None) { + if (bgConfig.type == "none") { [self.layer removeAnimationForKey:kAnimKeyBackgroundColor]; } else { CGColorRef fromColor = (__bridge CGColorRef) @@ -668,10 +641,9 @@ - (void)updateProps:(const Props::Shared &)props } } - // If per-property arrays are populated and all changed properties resolved - // to 'none', no animations were queued. Fire onTransitionEnd immediately. - if (perProp && anyPropertyChanged && _pendingAnimationCount == 0 && - _eventEmitter) { + // If all changed properties resolved to 'none', no animations were queued. + // Fire onTransitionEnd immediately. + if (anyPropertyChanged && _pendingAnimationCount == 0 && _eventEmitter) { auto emitter = std::static_pointer_cast(_eventEmitter); emitter->onTransitionEnd(EaseViewEventEmitter::OnTransitionEnd{ diff --git a/src/EaseView.tsx b/src/EaseView.tsx index ca0287f..f1c60e8 100644 --- a/src/EaseView.tsx +++ b/src/EaseView.tsx @@ -59,8 +59,8 @@ const EASING_PRESETS: Record = { easeInOut: [0.42, 0, 0.58, 1], }; -/** Property index order for per-property arrays. */ -const PROPERTY_KEYS: (keyof AnimateProps)[] = [ +/** Transition struct field names (matches NativeTransitions keys). */ +const TRANSITION_KEYS = [ 'opacity', 'translateX', 'translateY', @@ -71,111 +71,190 @@ const PROPERTY_KEYS: (keyof AnimateProps)[] = [ 'rotateY', 'borderRadius', 'backgroundColor', -]; +] as const; -const PROPERTY_COUNT = PROPERTY_KEYS.length; +type TransitionKey = (typeof TRANSITION_KEYS)[number]; + +/** Transform property keys (indices 1-7) get spring defaults; others get timing. */ +const TRANSFORM_KEYS = new Set([ + 'translateX', + 'translateY', + 'scaleX', + 'scaleY', + 'rotate', + 'rotateX', + 'rotateY', +]); /** Returns true if the transition is a SingleTransition (has a `type` field). */ function isSingleTransition(t: Transition): t is SingleTransition { return 'type' in t; } -/** Library defaults: spring for transforms (indices 1-7), timing 300ms easeInOut for others. */ -const TIMING_DEFAULT: SingleTransition = { +/** Resolved native transition config for a single property. */ +type NativeTransitionConfig = { + type: string; + duration: number; + easingBezier: number[]; + damping: number; + stiffness: number; + mass: number; + loop: string; + delay: number; +}; + +/** Full transitions struct passed to native. */ +type NativeTransitions = { + defaultConfig: NativeTransitionConfig; + opacity: NativeTransitionConfig; + translateX: NativeTransitionConfig; + translateY: NativeTransitionConfig; + scaleX: NativeTransitionConfig; + scaleY: NativeTransitionConfig; + rotate: NativeTransitionConfig; + rotateX: NativeTransitionConfig; + rotateY: NativeTransitionConfig; + borderRadius: NativeTransitionConfig; + backgroundColor: NativeTransitionConfig; +}; + +/** Library defaults: spring for transforms, timing 300ms easeInOut for others. */ +const TIMING_DEFAULT_CONFIG: NativeTransitionConfig = { type: 'timing', duration: 300, - easing: 'easeInOut', + easingBezier: [0.42, 0, 0.58, 1], + damping: 15, + stiffness: 120, + mass: 1, + loop: 'none', + delay: 0, }; -const SPRING_DEFAULT: SingleTransition = { + +const SPRING_DEFAULT_CONFIG: NativeTransitionConfig = { type: 'spring', + duration: 300, + easingBezier: [0.42, 0, 0.58, 1], damping: 15, stiffness: 120, mass: 1, + loop: 'none', + delay: 0, }; -function getLibraryDefault(index: number): SingleTransition { - // Indices 1-7 are transforms → spring default - // Indices 0,8,9 are opacity, borderRadius, backgroundColor → timing default - return index >= 1 && index <= 7 ? SPRING_DEFAULT : TIMING_DEFAULT; +function getLibraryDefault(key: TransitionKey): NativeTransitionConfig { + return TRANSFORM_KEYS.has(key) + ? SPRING_DEFAULT_CONFIG + : TIMING_DEFAULT_CONFIG; } -/** Resolve a SingleTransition into flat scalar values. */ -function resolveSingleConfig(config: SingleTransition) { - const type = config.type as 'timing' | 'spring' | 'none'; +/** Resolve a SingleTransition into a native config object. */ +function resolveSingleConfig(config: SingleTransition): NativeTransitionConfig { + const type = config.type as string; const duration = config.type === 'timing' ? config.duration ?? 300 : 300; const rawEasing = config.type === 'timing' ? config.easing ?? 'easeInOut' : 'easeInOut'; - const bezier: CubicBezier = Array.isArray(rawEasing) + if (__DEV__) { + if (Array.isArray(rawEasing)) { + if ((rawEasing as number[]).length !== 4) { + console.warn( + 'react-native-ease: Custom easing must be a [x1, y1, x2, y2] tuple (got length ' + + (rawEasing as number[]).length + + ').', + ); + } + if ( + rawEasing[0] < 0 || + rawEasing[0] > 1 || + rawEasing[2] < 0 || + rawEasing[2] > 1 + ) { + console.warn( + 'react-native-ease: Easing x-values (x1, x2) must be between 0 and 1.', + ); + } + } + } + const easingBezier: number[] = Array.isArray(rawEasing) ? rawEasing : EASING_PRESETS[rawEasing]!; const damping = config.type === 'spring' ? config.damping ?? 15 : 15; const stiffness = config.type === 'spring' ? config.stiffness ?? 120 : 120; const mass = config.type === 'spring' ? config.mass ?? 1 : 1; - const loop: 'none' | 'repeat' | 'reverse' = + const loop: string = config.type === 'timing' ? config.loop ?? 'none' : 'none'; - return { type, duration, bezier, damping, stiffness, mass, loop }; + const delay = + config.type === 'timing' || config.type === 'spring' + ? config.delay ?? 0 + : 0; + return { + type, + duration, + easingBezier, + damping, + stiffness, + mass, + loop, + delay, + }; } -interface PerPropertyArrays { - types: string[]; - durations: number[]; - dampings: number[]; - stiffnesses: number[]; - masses: number[]; - loops: string[]; - easingBeziers: number[]; -} +/** Resolve the transition prop into a fully-populated NativeTransitions struct. */ +function resolveTransitions(transition?: Transition): NativeTransitions { + // Single transition: apply the same config to all 11 slots + if (transition != null && isSingleTransition(transition)) { + const config = resolveSingleConfig(transition); + const result = { defaultConfig: config } as Record< + string, + NativeTransitionConfig + >; + for (const key of TRANSITION_KEYS) { + result[key] = config; + } + return result as unknown as NativeTransitions; + } -function resolvePerPropertyTransitions( - transitionMap: Exclude, -): { - scalars: ReturnType; - arrays: PerPropertyArrays; -} { - const arrays: PerPropertyArrays = { - types: [], - durations: [], - dampings: [], - stiffnesses: [], - masses: [], - loops: [], - easingBeziers: [], - }; + // No transition: use library defaults per category + if (transition == null) { + const result = { defaultConfig: TIMING_DEFAULT_CONFIG } as Record< + string, + NativeTransitionConfig + >; + for (const key of TRANSITION_KEYS) { + result[key] = getLibraryDefault(key); + } + return result as unknown as NativeTransitions; + } - const defaultConfig = transitionMap.default; + // TransitionMap: resolve per property + const transitionMap = transition; + const defaultSingle = transitionMap.default; + const defaultNative = defaultSingle + ? resolveSingleConfig(defaultSingle) + : undefined; + + const result = { + defaultConfig: defaultNative ?? TIMING_DEFAULT_CONFIG, + } as Record; - for (let i = 0; i < PROPERTY_COUNT; i++) { - const key = PROPERTY_KEYS[i]!; - // Resolution order: specific key → scale shorthand (for scaleX/scaleY) → default → library default - let config: SingleTransition; - if (transitionMap[key] != null) { - config = transitionMap[key]!; + for (const key of TRANSITION_KEYS) { + const specific = transitionMap[key as keyof typeof transitionMap] as + | SingleTransition + | undefined; + if (specific != null) { + result[key] = resolveSingleConfig(specific); } else if ( (key === 'scaleX' || key === 'scaleY') && transitionMap.scale != null ) { - config = transitionMap.scale!; - } else if (defaultConfig != null) { - config = defaultConfig; + result[key] = resolveSingleConfig(transitionMap.scale!); + } else if (defaultNative) { + result[key] = defaultNative; } else { - config = getLibraryDefault(i); + result[key] = getLibraryDefault(key); } - - const resolved = resolveSingleConfig(config); - arrays.types.push(resolved.type); - arrays.durations.push(resolved.duration); - arrays.dampings.push(resolved.damping); - arrays.stiffnesses.push(resolved.stiffness); - arrays.masses.push(resolved.mass); - arrays.loops.push(resolved.loop); - arrays.easingBeziers.push(...resolved.bezier); } - // Scalar props = default key values (or library defaults for opacity category) - const scalarConfig = defaultConfig ?? TIMING_DEFAULT; - const scalars = resolveSingleConfig(scalarConfig); - - return { scalars, arrays }; + return result as unknown as NativeTransitions; } export type EaseViewProps = ViewProps & { @@ -299,81 +378,8 @@ export function EaseView({ } } - // Resolve transition config — single config or per-property map - const isMap = transition != null && !isSingleTransition(transition); - const singleTransition = transition == null || isMap ? undefined : transition; - - // Single config resolution (used when single transition or as scalars for map) - let transitionType: 'timing' | 'spring' | 'none'; - let transitionDuration: number; - let bezier: CubicBezier; - let transitionDamping: number; - let transitionStiffness: number; - let transitionMass: number; - let transitionLoop: 'none' | 'repeat' | 'reverse'; - let perPropertyArrays: PerPropertyArrays | undefined; - - if (isMap) { - const { scalars, arrays } = resolvePerPropertyTransitions(transition); - transitionType = scalars.type; - transitionDuration = scalars.duration; - bezier = scalars.bezier; - transitionDamping = scalars.damping; - transitionStiffness = scalars.stiffness; - transitionMass = scalars.mass; - transitionLoop = scalars.loop; - perPropertyArrays = arrays; - } else { - transitionType = singleTransition?.type ?? 'timing'; - transitionDuration = - singleTransition?.type === 'timing' - ? singleTransition.duration ?? 300 - : 300; - const rawEasing = - singleTransition?.type === 'timing' - ? singleTransition.easing ?? 'easeInOut' - : 'easeInOut'; - if (__DEV__) { - if (Array.isArray(rawEasing)) { - if ((rawEasing as number[]).length !== 4) { - console.warn( - 'react-native-ease: Custom easing must be a [x1, y1, x2, y2] tuple (got length ' + - (rawEasing as number[]).length + - ').', - ); - } - if ( - rawEasing[0] < 0 || - rawEasing[0] > 1 || - rawEasing[2] < 0 || - rawEasing[2] > 1 - ) { - console.warn( - 'react-native-ease: Easing x-values (x1, x2) must be between 0 and 1.', - ); - } - } - } - bezier = Array.isArray(rawEasing) ? rawEasing : EASING_PRESETS[rawEasing]!; - transitionDamping = - singleTransition?.type === 'spring' ? singleTransition.damping ?? 15 : 15; - transitionStiffness = - singleTransition?.type === 'spring' - ? singleTransition.stiffness ?? 120 - : 120; - transitionMass = - singleTransition?.type === 'spring' ? singleTransition.mass ?? 1 : 1; - transitionLoop = - singleTransition?.type === 'timing' - ? singleTransition.loop ?? 'none' - : 'none'; - } - const singleTrans = - transition && 'type' in transition ? transition : undefined; - const transitionDelay = - singleTrans?.type === 'timing' || singleTrans?.type === 'spring' - ? singleTrans.delay ?? 0 - : 0; + // Resolve transition config into a fully-populated struct + const transitions = resolveTransitions(transition); const handleTransitionEnd = onTransitionEnd ? (event: { nativeEvent: { finished: boolean } }) => @@ -405,21 +411,7 @@ export function EaseView({ initialAnimateRotateY={resolvedInitial.rotateY} initialAnimateBorderRadius={resolvedInitial.borderRadius} initialAnimateBackgroundColor={initialBgColor} - transitionType={transitionType} - transitionDuration={transitionDuration} - transitionEasingBezier={bezier} - transitionDamping={transitionDamping} - transitionStiffness={transitionStiffness} - transitionMass={transitionMass} - transitionLoop={transitionLoop} - transitionDelay={transitionDelay} - perPropertyTransitionTypes={perPropertyArrays?.types} - perPropertyTransitionDurations={perPropertyArrays?.durations} - perPropertyTransitionDampings={perPropertyArrays?.dampings} - perPropertyTransitionStiffnesses={perPropertyArrays?.stiffnesses} - perPropertyTransitionMasses={perPropertyArrays?.masses} - perPropertyTransitionLoops={perPropertyArrays?.loops} - perPropertyTransitionEasingBeziers={perPropertyArrays?.easingBeziers} + transitions={transitions} useHardwareLayer={useHardwareLayer} transformOriginX={transformOrigin?.x ?? 0.5} transformOriginY={transformOrigin?.y ?? 0.5} diff --git a/src/EaseViewNativeComponent.ts b/src/EaseViewNativeComponent.ts index d12190e..c0a3c4b 100644 --- a/src/EaseViewNativeComponent.ts +++ b/src/EaseViewNativeComponent.ts @@ -6,6 +6,34 @@ import { type ColorValue, } from 'react-native'; +type Float = CodegenTypes.Float; +type Int32 = CodegenTypes.Int32; + +type NativeTransitionConfig = Readonly<{ + type: string; + duration: Int32; + easingBezier: ReadonlyArray; + damping: Float; + stiffness: Float; + mass: Float; + loop: string; + delay: Int32; +}>; + +type NativeTransitions = Readonly<{ + defaultConfig: NativeTransitionConfig; + opacity: NativeTransitionConfig; + translateX: NativeTransitionConfig; + translateY: NativeTransitionConfig; + scaleX: NativeTransitionConfig; + scaleY: NativeTransitionConfig; + rotate: NativeTransitionConfig; + rotateX: NativeTransitionConfig; + rotateY: NativeTransitionConfig; + borderRadius: NativeTransitionConfig; + backgroundColor: NativeTransitionConfig; +}>; + export interface NativeProps extends ViewProps { // Bitmask of which properties are animated (0 = none, let style handle all) animatedProperties?: CodegenTypes.WithDefault; @@ -37,33 +65,8 @@ export interface NativeProps extends ViewProps { >; initialAnimateBackgroundColor?: ColorValue; - // Transition config - transitionType?: CodegenTypes.WithDefault< - 'timing' | 'spring' | 'none', - 'timing' - >; - transitionDuration?: CodegenTypes.WithDefault; - // Easing cubic bezier control points [x1, y1, x2, y2] (default: easeInOut) - transitionEasingBezier?: ReadonlyArray; - transitionDamping?: CodegenTypes.WithDefault; - transitionStiffness?: CodegenTypes.WithDefault; - transitionMass?: CodegenTypes.WithDefault; - transitionLoop?: CodegenTypes.WithDefault< - 'none' | 'repeat' | 'reverse', - 'none' - >; - transitionDelay?: CodegenTypes.WithDefault; - - // Per-property transition arrays (10 elements each, one per animatable property) - // Index order: 0=opacity, 1=translateX, 2=translateY, 3=scaleX, 4=scaleY, - // 5=rotate, 6=rotateX, 7=rotateY, 8=borderRadius, 9=backgroundColor - perPropertyTransitionTypes?: ReadonlyArray; - perPropertyTransitionDurations?: ReadonlyArray; - perPropertyTransitionDampings?: ReadonlyArray; - perPropertyTransitionStiffnesses?: ReadonlyArray; - perPropertyTransitionMasses?: ReadonlyArray; - perPropertyTransitionLoops?: ReadonlyArray; - perPropertyTransitionEasingBeziers?: ReadonlyArray; // 40 elements (4 per property) + // Unified transition config — one struct with per-property configs + transitions?: NativeTransitions; // Transform origin (0–1 fractions, default center) transformOriginX?: CodegenTypes.WithDefault; diff --git a/src/__tests__/EaseView.test.tsx b/src/__tests__/EaseView.test.tsx index dfc3526..49ab262 100644 --- a/src/__tests__/EaseView.test.tsx +++ b/src/__tests__/EaseView.test.tsx @@ -127,16 +127,25 @@ describe('EaseView', () => { }); describe('transition defaults', () => { - it('defaults to timing with standard values', () => { + it('uses library defaults per category when no transition', () => { render(); const props = getNativeProps(); - expect(props.transitionType).toBe('timing'); - expect(props.transitionDuration).toBe(300); - expect(props.transitionEasingBezier).toEqual([0.42, 0, 0.58, 1]); - expect(props.transitionLoop).toBe('none'); - }); - - it('resolves timing transition props', () => { + const t = props.transitions; + // defaultConfig = timing (library default for non-transform) + expect(t.defaultConfig.type).toBe('timing'); + expect(t.defaultConfig.duration).toBe(300); + expect(t.defaultConfig.easingBezier).toEqual([0.42, 0, 0.58, 1]); + expect(t.defaultConfig.loop).toBe('none'); + expect(t.defaultConfig.delay).toBe(0); + // opacity (non-transform) → timing default + expect(t.opacity.type).toBe('timing'); + // translateX (transform) → spring default + expect(t.translateX.type).toBe('spring'); + expect(t.translateX.damping).toBe(15); + expect(t.translateX.stiffness).toBe(120); + }); + + it('resolves timing transition to all slots', () => { render( { }} />, ); - const props = getNativeProps(); - expect(props.transitionType).toBe('timing'); - expect(props.transitionDuration).toBe(500); - expect(props.transitionEasingBezier).toEqual([0, 0, 1, 1]); - expect(props.transitionLoop).toBe('reverse'); + const t = getNativeProps().transitions; + expect(t.defaultConfig.type).toBe('timing'); + expect(t.defaultConfig.duration).toBe(500); + expect(t.defaultConfig.easingBezier).toEqual([0, 0, 1, 1]); + expect(t.defaultConfig.loop).toBe('reverse'); + // All properties get the same config + expect(t.opacity.type).toBe('timing'); + expect(t.opacity.duration).toBe(500); + expect(t.translateX.type).toBe('timing'); + expect(t.translateX.duration).toBe(500); }); - it('resolves spring transition props with timing defaults for unused fields', () => { + it('resolves spring transition with defaults for unused fields', () => { render( , ); - const props = getNativeProps(); - expect(props.transitionType).toBe('spring'); - expect(props.transitionDamping).toBe(20); - expect(props.transitionStiffness).toBe(200); - expect(props.transitionMass).toBe(2); - // Timing-specific fields get defaults (easeInOut bezier) - expect(props.transitionDuration).toBe(300); - expect(props.transitionEasingBezier).toEqual([0.42, 0, 0.58, 1]); - expect(props.transitionLoop).toBe('none'); + const t = getNativeProps().transitions; + expect(t.defaultConfig.type).toBe('spring'); + expect(t.defaultConfig.damping).toBe(20); + expect(t.defaultConfig.stiffness).toBe(200); + expect(t.defaultConfig.mass).toBe(2); + // Timing-specific fields get defaults + expect(t.defaultConfig.duration).toBe(300); + expect(t.defaultConfig.easingBezier).toEqual([0.42, 0, 0.58, 1]); + expect(t.defaultConfig.loop).toBe('none'); }); it('uses spring defaults when only type is specified', () => { render(); - const props = getNativeProps(); - expect(props.transitionDamping).toBe(15); - expect(props.transitionStiffness).toBe(120); - expect(props.transitionMass).toBe(1); + const t = getNativeProps().transitions; + expect(t.defaultConfig.damping).toBe(15); + expect(t.defaultConfig.stiffness).toBe(120); + expect(t.defaultConfig.mass).toBe(1); }); - it('passes none transition type', () => { + it('passes none transition type to all slots', () => { render(); - expect(getNativeProps().transitionType).toBe('none'); + const t = getNativeProps().transitions; + expect(t.defaultConfig.type).toBe('none'); + expect(t.opacity.type).toBe('none'); + expect(t.translateX.type).toBe('none'); }); it('passes custom cubic bezier control points', () => { @@ -197,8 +214,8 @@ describe('EaseView', () => { }} />, ); - const props = getNativeProps(); - expect(props.transitionEasingBezier).toEqual([0.25, 0.1, 0.25, 1.0]); + const t = getNativeProps().transitions; + expect(t.defaultConfig.easingBezier).toEqual([0.25, 0.1, 0.25, 1.0]); }); it('warns for invalid array length', () => { @@ -234,6 +251,23 @@ describe('EaseView', () => { ); spy.mockRestore(); }); + + it('passes delay for timing transition', () => { + render( + , + ); + const t = getNativeProps().transitions; + expect(t.defaultConfig.delay).toBe(200); + expect(t.opacity.delay).toBe(200); + }); + + it('passes delay for spring transition', () => { + render( + , + ); + const t = getNativeProps().transitions; + expect(t.defaultConfig.delay).toBe(150); + }); }); describe('useHardwareLayer', () => { @@ -460,21 +494,20 @@ describe('EaseView', () => { }); describe('per-property transition map', () => { - it('does not pass arrays for single transition (backward compat)', () => { + it('populates all slots from single transition', () => { render( , ); - const props = getNativeProps(); - expect(props.perPropertyTransitionTypes).toBeUndefined(); - expect(props.perPropertyTransitionDurations).toBeUndefined(); - expect(props.perPropertyTransitionDampings).toBeUndefined(); - expect(props.perPropertyTransitionStiffnesses).toBeUndefined(); - expect(props.perPropertyTransitionMasses).toBeUndefined(); - expect(props.perPropertyTransitionLoops).toBeUndefined(); - expect(props.perPropertyTransitionEasingBeziers).toBeUndefined(); + const t = getNativeProps().transitions; + // All slots get the same config + expect(t.opacity.type).toBe('spring'); + expect(t.opacity.damping).toBe(20); + expect(t.translateX.type).toBe('spring'); + expect(t.translateX.damping).toBe(20); + expect(t.backgroundColor.type).toBe('spring'); }); - it('populates arrays with default-only map (all slots same)', () => { + it('populates all slots with default-only map', () => { render( { }} />, ); - const props = getNativeProps(); - expect(props.perPropertyTransitionTypes).toHaveLength(10); - expect(props.perPropertyTransitionTypes).toEqual( - Array(10).fill('timing'), - ); - expect(props.perPropertyTransitionDurations).toEqual(Array(10).fill(500)); - // Scalar props should match default - expect(props.transitionType).toBe('timing'); - expect(props.transitionDuration).toBe(500); + const t = getNativeProps().transitions; + expect(t.defaultConfig.type).toBe('timing'); + expect(t.defaultConfig.duration).toBe(500); + expect(t.opacity.type).toBe('timing'); + expect(t.opacity.duration).toBe(500); + expect(t.translateX.type).toBe('timing'); + expect(t.translateX.duration).toBe(500); }); it('applies property-specific overrides', () => { @@ -505,17 +536,17 @@ describe('EaseView', () => { }} />, ); - const props = getNativeProps(); - // Index 0 = opacity: timing 150ms - expect(props.perPropertyTransitionTypes[0]).toBe('timing'); - expect(props.perPropertyTransitionDurations[0]).toBe(150); - // Index 2 = translateY: spring - expect(props.perPropertyTransitionTypes[2]).toBe('spring'); - expect(props.perPropertyTransitionDampings[2]).toBe(20); - expect(props.perPropertyTransitionStiffnesses[2]).toBe(200); - // Index 1 = translateX: default timing 300ms - expect(props.perPropertyTransitionTypes[1]).toBe('timing'); - expect(props.perPropertyTransitionDurations[1]).toBe(300); + const t = getNativeProps().transitions; + // opacity: timing 150ms + expect(t.opacity.type).toBe('timing'); + expect(t.opacity.duration).toBe(150); + // translateY: spring + expect(t.translateY.type).toBe('spring'); + expect(t.translateY.damping).toBe(20); + expect(t.translateY.stiffness).toBe(200); + // translateX: default timing 300ms + expect(t.translateX.type).toBe('timing'); + expect(t.translateX.duration).toBe(300); }); it('applies scale shorthand to scaleX and scaleY', () => { @@ -528,12 +559,11 @@ describe('EaseView', () => { }} />, ); - const props = getNativeProps(); - // Index 3 = scaleX, Index 4 = scaleY - expect(props.perPropertyTransitionTypes[3]).toBe('spring'); - expect(props.perPropertyTransitionTypes[4]).toBe('spring'); - expect(props.perPropertyTransitionDampings[3]).toBe(10); - expect(props.perPropertyTransitionDampings[4]).toBe(10); + const t = getNativeProps().transitions; + expect(t.scaleX.type).toBe('spring'); + expect(t.scaleY.type).toBe('spring'); + expect(t.scaleX.damping).toBe(10); + expect(t.scaleY.damping).toBe(10); }); it('allows scaleX to override scale shorthand', () => { @@ -547,13 +577,13 @@ describe('EaseView', () => { }} />, ); - const props = getNativeProps(); - // scaleX (index 3) uses specific override - expect(props.perPropertyTransitionTypes[3]).toBe('timing'); - expect(props.perPropertyTransitionDurations[3]).toBe(200); - // scaleY (index 4) falls back to scale shorthand - expect(props.perPropertyTransitionTypes[4]).toBe('spring'); - expect(props.perPropertyTransitionDampings[4]).toBe(10); + const t = getNativeProps().transitions; + // scaleX uses specific override + expect(t.scaleX.type).toBe('timing'); + expect(t.scaleX.duration).toBe(200); + // scaleY falls back to scale shorthand + expect(t.scaleY.type).toBe('spring'); + expect(t.scaleY.damping).toBe(10); }); it('uses library defaults by category when no default key', () => { @@ -565,39 +595,35 @@ describe('EaseView', () => { }} />, ); - const props = getNativeProps(); - // opacity (index 0) is explicitly set - expect(props.perPropertyTransitionTypes[0]).toBe('timing'); - expect(props.perPropertyTransitionDurations[0]).toBe(150); - // translateX (index 1) — transform category → spring default - expect(props.perPropertyTransitionTypes[1]).toBe('spring'); - expect(props.perPropertyTransitionDampings[1]).toBe(15); - expect(props.perPropertyTransitionStiffnesses[1]).toBe(120); - // borderRadius (index 8) — non-transform → timing default - expect(props.perPropertyTransitionTypes[8]).toBe('timing'); - expect(props.perPropertyTransitionDurations[8]).toBe(300); - // backgroundColor (index 9) — non-transform → timing default - expect(props.perPropertyTransitionTypes[9]).toBe('timing'); - }); - - it('flattens easing beziers into 40-element array', () => { + const t = getNativeProps().transitions; + // opacity is explicitly set + expect(t.opacity.type).toBe('timing'); + expect(t.opacity.duration).toBe(150); + // translateX — transform category → spring default + expect(t.translateX.type).toBe('spring'); + expect(t.translateX.damping).toBe(15); + expect(t.translateX.stiffness).toBe(120); + // borderRadius — non-transform → timing default + expect(t.borderRadius.type).toBe('timing'); + expect(t.borderRadius.duration).toBe(300); + // backgroundColor — non-transform → timing default + expect(t.backgroundColor.type).toBe('timing'); + }); + + it('supports per-property delay in transition map', () => { render( , ); - const props = getNativeProps(); - expect(props.perPropertyTransitionEasingBeziers).toHaveLength(40); - // linear = [0, 0, 1, 1] repeated 10 times - for (let i = 0; i < 10; i++) { - expect(props.perPropertyTransitionEasingBeziers[i * 4]).toBe(0); - expect(props.perPropertyTransitionEasingBeziers[i * 4 + 1]).toBe(0); - expect(props.perPropertyTransitionEasingBeziers[i * 4 + 2]).toBe(1); - expect(props.perPropertyTransitionEasingBeziers[i * 4 + 3]).toBe(1); - } + const t = getNativeProps().transitions; + expect(t.opacity.delay).toBe(50); + expect(t.translateX.delay).toBe(100); + expect(t.scaleX.delay).toBe(100); }); }); }); From 7146763390301ef9f712dd4697b4f544ce00ed10 Mon Sep 17 00:00:00 2001 From: Janic Duplessis Date: Mon, 16 Mar 2026 19:09:53 -0400 Subject: [PATCH 6/6] fix(example): slow down per-property demo for clearer video --- example/src/demos/PerPropertyDemo.tsx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/example/src/demos/PerPropertyDemo.tsx b/example/src/demos/PerPropertyDemo.tsx index 4c7609d..6ecc6ba 100644 --- a/example/src/demos/PerPropertyDemo.tsx +++ b/example/src/demos/PerPropertyDemo.tsx @@ -10,16 +10,17 @@ export function PerPropertyDemo() { return (
- Opacity fades with timing 150ms, translateX springs independently + Opacity fades slowly (1.5s timing), translateX slides with a bouncy + spring — each property animates independently