@rootnative/inertia 0.0.0-alpha.7 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +1 -1
  3. package/dist/{chunk-ALRHDFZE.mjs → chunk-2DHKV2XY.mjs} +1 -1
  4. package/dist/chunk-34Q4UM6V.js +8 -0
  5. package/dist/{chunk-CWLFUYIY.mjs → chunk-HFDZAHWP.mjs} +1 -1
  6. package/dist/{chunk-7UDYEFBU.js → chunk-IWLU3VDE.js} +361 -288
  7. package/dist/chunk-KYJROYCG.js +8 -0
  8. package/dist/{chunk-DWCLIBYO.mjs → chunk-LYMLQ6WQ.mjs} +362 -289
  9. package/dist/{chunk-TDSO63CJ.js → chunk-NKA6XR77.js} +2 -2
  10. package/dist/{chunk-6SMPIOIC.mjs → chunk-TUMNV4P7.mjs} +1 -1
  11. package/dist/{chunk-2HYD2ZBK.js → chunk-TUYHTHVV.js} +2 -2
  12. package/dist/{chunk-NXDJZD6A.mjs → chunk-V6BTXHZK.mjs} +1 -1
  13. package/dist/chunk-X5J5M3K3.js +8 -0
  14. package/dist/{chunk-JVBXPF2G.mjs → chunk-ZN3PNGHQ.mjs} +1 -1
  15. package/dist/index.d.mts +229 -43
  16. package/dist/index.d.ts +229 -43
  17. package/dist/index.js +199 -23
  18. package/dist/index.mjs +191 -18
  19. package/dist/motion/Image.js +3 -3
  20. package/dist/motion/Image.mjs +2 -2
  21. package/dist/motion/Pressable.js +3 -3
  22. package/dist/motion/Pressable.mjs +2 -2
  23. package/dist/motion/ScrollView.js +3 -3
  24. package/dist/motion/ScrollView.mjs +2 -2
  25. package/dist/motion/Text.js +3 -3
  26. package/dist/motion/Text.mjs +2 -2
  27. package/dist/motion/View.js +3 -3
  28. package/dist/motion/View.mjs +2 -2
  29. package/llms.txt +6 -1
  30. package/package.json +1 -1
  31. package/src/index.ts +10 -0
  32. package/src/motion/createMotionComponent.tsx +624 -501
  33. package/src/values/index.ts +13 -0
  34. package/src/values/useAnimation.ts +15 -1
  35. package/src/values/useAnimator.ts +72 -0
  36. package/src/values/useColorCascade.ts +107 -0
  37. package/src/values/useInterpolatedStyle.ts +319 -0
  38. package/src/values/useMotionValue.ts +20 -2
  39. package/src/values/useSpring.ts +12 -0
  40. package/dist/chunk-3UTJJ4A3.js +0 -8
  41. package/dist/chunk-4QGXK6TF.js +0 -8
  42. package/dist/chunk-Z7HIOFKQ.js +0 -8
package/dist/index.d.ts CHANGED
@@ -339,6 +339,50 @@ declare function buildReleaseAnimation(transition: TransitionConfig, toValue: nu
339
339
  */
340
340
  declare function useAnimation(target: number, transition?: TransitionInput): SharedValue<number>;
341
341
 
342
+ /**
343
+ * Imperative setter that drives a `SharedValue<number>` toward `to`, resolving
344
+ * the transition through the **same context** the declarative surface uses. It
345
+ * is the imperative escape hatch that closes the two footguns of writing
346
+ * `value.value = resolveTransition(config, to)` by hand from an event handler:
347
+ *
348
+ * 1. **Named transitions resolve.** A `TransitionName` registered on the
349
+ * nearest `<MotionConfig transitions>` works here just as it does on the
350
+ * `transition` prop or in `useAnimation`. Raw `resolveTransition` can't
351
+ * reach the registry (names resolve via context), so imperative call sites
352
+ * otherwise rebuild configs the provider already owns.
353
+ * 2. **Reduced motion is respected.** Writes route through the same
354
+ * `no-animation` downgrade `useAnimation` applies under
355
+ * `<MotionConfig reducedMotion>`. Hand-rolled `resolveTransition` writes
356
+ * silently bypass that setting — a correctness bug this hook fixes.
357
+ *
358
+ * The returned callback is stable across renders (it reads the registry and
359
+ * the reduced-motion flag live inside the body), so it can be dropped straight
360
+ * into memoized handlers.
361
+ *
362
+ * This is not a new animation API — it starts animations in Inertia's existing
363
+ * transition vocabulary, so it does not conflict with the "no imperative-only
364
+ * APIs that bypass the declarative surface" scope rule. It is the hooks-layer
365
+ * equivalent of `useMotionValue` + `resolveTransition`, minus the footguns.
366
+ *
367
+ * @example
368
+ * ```tsx
369
+ * const hovered = useMotionValue(0)
370
+ * const animate = useAnimator()
371
+ *
372
+ * const onHoverIn = () => animate(hovered, 1, 'state-hover')
373
+ * const onHoverOut = () => animate(hovered, 0, 'state-hover')
374
+ * ```
375
+ *
376
+ * @example
377
+ * ```tsx
378
+ * // Inline config works too; default is spring when omitted.
379
+ * animate(progress, 1, { type: 'timing', duration: 150 })
380
+ * animate(progress, 0) // spring
381
+ * ```
382
+ */
383
+ type Animator = (value: SharedValue<number>, to: number, transition?: TransitionInput) => void;
384
+ declare function useAnimator(): Animator;
385
+
342
386
  /**
343
387
  * Toggle a 0↔1 progress value with a spring whenever `active` flips.
344
388
  *
@@ -406,56 +450,64 @@ interface UseColorTransitionOptions {
406
450
  declare function useColorTransition(progress: SharedValue<number>, range: readonly [string, string], options?: UseColorTransitionOptions): ReturnType<typeof useAnimatedStyle>;
407
451
 
408
452
  /**
409
- * Create an animatable value owned by JS but readable from worklets.
410
- *
411
- * This is the escape-hatch primitive that the rest of the value-layer hooks
412
- * (`useSpring`, `useTransform`, `useScroll`) compose against. It is a thin
413
- * pass-through over Reanimated's `useSharedValue`: a `SharedValue<T>` with
414
- * `.value` for direct reads/writes (UI-thread reads in worklets, JS-thread
415
- * writes from event handlers / effects).
453
+ * One layer in a color cascade: its own `progress` shared value (0→1) and the
454
+ * color it blends toward as that progress rises. Layers are ordered lowest
455
+ * priority first; a later layer wins over an earlier one at equal progress.
456
+ */
457
+ interface ColorCascadeLayer {
458
+ /** 0→1 driver for this layer. Drive it upstream (spring / boolean / gesture). */
459
+ progress: SharedValue<number>;
460
+ /** The color this layer blends toward as `progress` moves 0→1. */
461
+ color: string;
462
+ }
463
+ interface UseColorCascadeOptions {
464
+ /**
465
+ * Which style slot the composited color is emitted under. Defaults to
466
+ * `backgroundColor` — identical to `useColorTransition`. Override for ring
467
+ * colors (`borderColor`), text (`color`), image tints (`tintColor`), etc.
468
+ */
469
+ key?: ColorStyleKey;
470
+ }
471
+ /**
472
+ * Priority-ordered layered color crossfade: each layer owns an independent
473
+ * `progress` value and blends the accumulated color below it toward its own
474
+ * color as that progress moves 0→1. Later layers win over earlier ones — the
475
+ * array is priority order, **lowest first** (matching the `gesture` prop's
476
+ * fixed-priority cascade, Decision 5).
416
477
  *
417
- * We intentionally do not introduce a `MotionValue` wrapper class around the
418
- * shared value. The simplest object that interops with `useAnimatedStyle`,
419
- * `useDerivedValue`, and every other Reanimated API _is_ the shared value
420
- * itself; adding a `{ get, set, value }` shell would force consumers to
421
- * unwrap it at every Reanimated boundary and break worklet capture.
478
+ * Equivalent to the hand-chained nested-`interpolateColor` shape
479
+ * `focus(error(hover(rest)))`, collapsed into one hook and one worklet:
422
480
  *
423
- * Worklet read:
424
- * ```ts
425
- * const x = useMotionValue(0)
426
- * useAnimatedStyle(() => ({ transform: [{ translateX: x.value }] }))
427
- * ```
481
+ * ```tsx
482
+ * const borderStyle = useColorCascade(
483
+ * colors.border,
484
+ * [
485
+ * { progress: hovered, color: colors.borderHover },
486
+ * { progress: errored, color: colors.borderError },
487
+ * { progress: focused, color: colors.borderFocus },
488
+ * ],
489
+ * { key: 'borderColor' },
490
+ * )
428
491
  *
429
- * JS write:
430
- * ```ts
431
- * onPress={() => { x.value = 100 }}
492
+ * return <Motion.View style={[styles.field, borderStyle]} />
432
493
  * ```
433
- */
434
- declare function useMotionValue(initial: number): SharedValue<number>;
435
- declare function useMotionValue(initial: string): SharedValue<string>;
436
- declare function useMotionValue<T extends number | string>(initial: T): SharedValue<T>;
437
-
438
- /**
439
- * Animate a shared value toward `target` with spring physics, using the
440
- * library's react-spring vocabulary (`tension` / `friction` / `mass`).
441
494
  *
442
- * `target` may be a plain number or a `SharedValue<number>`. The plain-number
443
- * path drives the spring from a JS `useEffect`, so the animation re-runs on
444
- * every render where `target` changes. The shared-value path drives the
445
- * spring from a Reanimated reaction on the UI thread, so values produced by
446
- * gestures, scroll handlers, or other worklets flow through without bouncing
447
- * back to JS.
495
+ * This is a pure interpolator it does not animate on its own. Drive each
496
+ * layer's `progress` upstream with a `useSpring`, `useBooleanSpring`, gesture
497
+ * progress, or anything else producing a 0→1 shared value.
448
498
  *
449
- * Both call sites end up at the same `withSpring` invocation; the split is
450
- * just about which thread observes the source change.
499
+ * For the single-layer case (`rest` one active color), reach for
500
+ * [`useColorTransition`](./useColorTransition) it is the fast path and this
501
+ * hook is not a replacement for it. For a mixed numeric + color cascade, or
502
+ * function-valued layers, drop to a hand-rolled `useAnimatedStyle`.
451
503
  *
452
- * `config` also accepts a `TransitionName` registered on the nearest
453
- * `<MotionConfig transitions>`. Because this hook is spring-only, the name
454
- * must resolve to a spring config a name registered as timing / decay /
455
- * no-animation warns in dev and falls back to the default spring (reach for
456
- * `useAnimation` when the named transition's type should be honored).
504
+ * The layer chain is resolved once on the JS thread and memoized on a
505
+ * structural signature (colors + key), so a fresh-but-equal `layers` array
506
+ * each render produces no new UI-thread closure (CLAUDE.md principle 8). The
507
+ * `progress` shared values are read live in the worklet, so their identity is
508
+ * intentionally excluded from the signature.
457
509
  */
458
- declare function useSpring(target: number | SharedValue<number>, config?: SpringTransition | TransitionName): SharedValue<number>;
510
+ declare function useColorCascade(rest: string, layers: readonly ColorCascadeLayer[], options?: UseColorCascadeOptions): ReturnType<typeof useAnimatedStyle>;
459
511
 
460
512
  /**
461
513
  * Extrapolation behavior at the edges of the input range. Mirrors
@@ -509,6 +561,140 @@ declare function useTransform<T>(transformer: () => T): SharedValue<T>;
509
561
  declare function useTransform(value: SharedValue<number>, inputRange: readonly number[], outputRange: readonly number[], options?: UseTransformOptions): SharedValue<number>;
510
562
  declare function useTransform(value: SharedValue<number>, inputRange: readonly number[], outputRange: readonly string[], options?: UseTransformOptions): SharedValue<string>;
511
563
 
564
+ /**
565
+ * Numeric style keys `useInterpolatedStyle` can emit directly (not lifted into
566
+ * the transform array). Mirrors the flat numeric surface of the `animate`
567
+ * prop.
568
+ */
569
+ type NumericStyleKey = 'opacity' | 'width' | 'height' | 'borderRadius' | 'shadowOpacity' | 'shadowRadius' | 'elevation' | 'top' | 'left' | 'right' | 'bottom' | 'fontSize' | 'lineHeight' | 'letterSpacing' | 'borderWidth';
570
+ /**
571
+ * Transform keys, lifted into a `transform: [...]` array in the order they
572
+ * appear in the map — the same key-order convention the `animate` prop uses.
573
+ * `rotate` / `rotateX` / `rotateY` take numeric degrees and emit
574
+ * `'<n>deg'` strings.
575
+ */
576
+ type TransformKey = 'translateX' | 'translateY' | 'scale' | 'scaleX' | 'scaleY' | 'rotate' | 'rotateX' | 'rotateY';
577
+ /**
578
+ * Interpolation map: each entry maps `progress` onto an output range for one
579
+ * style or transform key. Numeric / transform keys take number stops; color
580
+ * keys take color-string stops. Mixing stop types per key is a compile error.
581
+ */
582
+ type InterpolatedStyleMap = {
583
+ [K in NumericStyleKey | TransformKey]?: readonly number[];
584
+ } & {
585
+ [K in ColorStyleKey]?: readonly string[];
586
+ };
587
+ interface UseInterpolatedStyleOptions {
588
+ /**
589
+ * Input range mapped onto every key's output range. Defaults to `[0, 1]`
590
+ * for 2-stop outputs, and to evenly-spaced stops across `[0, 1]` for
591
+ * longer outputs. When provided, it applies to all keys; a key whose
592
+ * output length differs from `inputRange.length` throws in dev.
593
+ */
594
+ inputRange?: readonly number[];
595
+ /**
596
+ * Edge behavior outside the input range. Defaults to `'clamp'`, matching
597
+ * `useColorTransition`. Applies to numeric keys; color interpolation
598
+ * always clamps (Reanimated's `interpolateColor` has no extrapolation
599
+ * option).
600
+ */
601
+ extrapolate?: ExtrapolationMode;
602
+ }
603
+ /**
604
+ * Map one `progress` shared value onto N style props via `interpolate` /
605
+ * `interpolateColor`, returning an animated style fragment that composes in a
606
+ * style array on any Reanimated-aware host (`Motion.*`, a hand-rolled
607
+ * `Animated.View`). The style-fragment counterpart to `useTransform`'s
608
+ * output-range form, in the same family as `useColorTransition` / `useShadow`.
609
+ *
610
+ * ```tsx
611
+ * const collapseStyle = useInterpolatedStyle(collapseProgress, {
612
+ * height: [expandedHeight, collapsedHeight],
613
+ * fontSize: [expanded.fontSize, collapsed.fontSize],
614
+ * })
615
+ *
616
+ * const labelStyle = useInterpolatedStyle(floatProgress, {
617
+ * translateY: [restingOffset, 0],
618
+ * scale: [restingScale, 1],
619
+ * })
620
+ *
621
+ * return <Motion.View style={[base, collapseStyle, labelStyle]} />
622
+ * ```
623
+ *
624
+ * This is a pure interpolator — it does not animate on its own. Drive
625
+ * `progress` upstream with a `useSpring`, `useBooleanSpring`, gesture
626
+ * progress, or scroll-derived `useTransform`.
627
+ *
628
+ * - Numeric / transform keys route through `interpolate`; color-string stops
629
+ * on a color key route through `interpolateColor` (a multi-stop
630
+ * `useColorTransition` without touching that hook).
631
+ * - Transform keys (`translateX`, `scale`, `rotate`, …) are lifted into a
632
+ * single `transform` array in the order they appear in the map. `rotate*`
633
+ * keys take numeric degrees and emit `'<n>deg'` strings, consistent with
634
+ * the `animate` surface.
635
+ * - `options.inputRange` defaults to `[0, 1]` for 2-stop outputs and to
636
+ * evenly-spaced stops otherwise. `options.extrapolate` defaults to
637
+ * `'clamp'`.
638
+ *
639
+ * For function-valued entries or multi-source composition, drop to a
640
+ * hand-rolled `useAnimatedStyle` (or `useTransform`'s worklet form) — this
641
+ * hook stays fully declarative and hashable so unchanged maps produce zero
642
+ * new UI-thread closures.
643
+ */
644
+ declare function useInterpolatedStyle(progress: SharedValue<number>, map: InterpolatedStyleMap, options?: UseInterpolatedStyleOptions): ReturnType<typeof useAnimatedStyle>;
645
+
646
+ /**
647
+ * Create an animatable value owned by JS but readable from worklets.
648
+ *
649
+ * This is the escape-hatch primitive that the rest of the value-layer hooks
650
+ * (`useSpring`, `useTransform`, `useScroll`) compose against. It is a thin
651
+ * pass-through over Reanimated's `useSharedValue`: a `SharedValue<T>` with
652
+ * `.value` for direct reads/writes (UI-thread reads in worklets, JS-thread
653
+ * writes from event handlers / effects).
654
+ *
655
+ * We intentionally do not introduce a `MotionValue` wrapper class around the
656
+ * shared value. The simplest object that interops with `useAnimatedStyle`,
657
+ * `useDerivedValue`, and every other Reanimated API _is_ the shared value
658
+ * itself; adding a `{ get, set, value }` shell would force consumers to
659
+ * unwrap it at every Reanimated boundary and break worklet capture.
660
+ *
661
+ * Worklet read:
662
+ * ```ts
663
+ * const x = useMotionValue(0)
664
+ * useAnimatedStyle(() => ({ transform: [{ translateX: x.value }] }))
665
+ * ```
666
+ *
667
+ * JS write:
668
+ * ```ts
669
+ * onPress={() => { x.value = 100 }}
670
+ * ```
671
+ */
672
+ declare function useMotionValue(initial: number): SharedValue<number>;
673
+ declare function useMotionValue(initial: string): SharedValue<string>;
674
+ declare function useMotionValue<T extends number | string>(initial: T): SharedValue<T>;
675
+
676
+ /**
677
+ * Animate a shared value toward `target` with spring physics, using the
678
+ * library's react-spring vocabulary (`tension` / `friction` / `mass`).
679
+ *
680
+ * `target` may be a plain number or a `SharedValue<number>`. The plain-number
681
+ * path drives the spring from a JS `useEffect`, so the animation re-runs on
682
+ * every render where `target` changes. The shared-value path drives the
683
+ * spring from a Reanimated reaction on the UI thread, so values produced by
684
+ * gestures, scroll handlers, or other worklets flow through without bouncing
685
+ * back to JS.
686
+ *
687
+ * Both call sites end up at the same `withSpring` invocation; the split is
688
+ * just about which thread observes the source change.
689
+ *
690
+ * `config` also accepts a `TransitionName` registered on the nearest
691
+ * `<MotionConfig transitions>`. Because this hook is spring-only, the name
692
+ * must resolve to a spring config — a name registered as timing / decay /
693
+ * no-animation warns in dev and falls back to the default spring (reach for
694
+ * `useAnimation` when the named transition's type should be honored).
695
+ */
696
+ declare function useSpring(target: number | SharedValue<number>, config?: SpringTransition | TransitionName): SharedValue<number>;
697
+
512
698
  interface UseScrollResult {
513
699
  /** Horizontal scroll offset in points. */
514
700
  scrollX: SharedValue<number>;
@@ -681,4 +867,4 @@ declare function useShadow({ from, to, progress, }: UseShadowOptions): ReturnTyp
681
867
  */
682
868
  declare function useVariants<V extends Readonly<Record<string, object>>>(variants: V, initial?: keyof V & string): VariantController<keyof V & string>;
683
869
 
684
- export { AnimatableValue, type BoxShadowLayer, type ColorStyleKey, EasingInput, type ExtrapolationMode, Motion, MotionComponent, MotionConfig, type MotionConfigProps, type MotionConfigValue, NamedTransitions, Presence, type PresenceContextValue, type ReducedMotion, type ShadowConfig, SpringTransition, TransitionConfig, TransitionInput, TransitionName, type UseColorTransitionOptions, type UseScrollResult, type UseShadowOptions, type UseTransformOptions, VariantController, buildReleaseAnimation, createMotionComponent, cubicBezier, ensureWorkletEasing, resolveAnimatableValue, resolveNamedTransition, resolveTransition, useAnimation, useBooleanSpring, useColorTransition, useMotionConfig, useMotionValue, useNamedTransitions, usePresence, useScroll, useShadow, useShouldReduceMotion, useSpring, useTransform, useVariants };
870
+ export { AnimatableValue, type Animator, type BoxShadowLayer, type ColorCascadeLayer, type ColorStyleKey, EasingInput, type ExtrapolationMode, type InterpolatedStyleMap, Motion, MotionComponent, MotionConfig, type MotionConfigProps, type MotionConfigValue, NamedTransitions, type NumericStyleKey, Presence, type PresenceContextValue, type ReducedMotion, type ShadowConfig, SpringTransition, type TransformKey, TransitionConfig, TransitionInput, TransitionName, type UseColorCascadeOptions, type UseColorTransitionOptions, type UseInterpolatedStyleOptions, type UseScrollResult, type UseShadowOptions, type UseTransformOptions, VariantController, buildReleaseAnimation, createMotionComponent, cubicBezier, ensureWorkletEasing, resolveAnimatableValue, resolveNamedTransition, resolveTransition, useAnimation, useAnimator, useBooleanSpring, useColorCascade, useColorTransition, useInterpolatedStyle, useMotionConfig, useMotionValue, useNamedTransitions, usePresence, useScroll, useShadow, useShouldReduceMotion, useSpring, useTransform, useVariants };
package/dist/index.js CHANGED
@@ -1,12 +1,12 @@
1
1
  'use strict';
2
2
 
3
3
  var chunk4PEHWDAZ_js = require('./chunk-4PEHWDAZ.js');
4
- var chunk4QGXK6TF_js = require('./chunk-4QGXK6TF.js');
5
- var chunkZ7HIOFKQ_js = require('./chunk-Z7HIOFKQ.js');
6
- var chunk3UTJJ4A3_js = require('./chunk-3UTJJ4A3.js');
7
- var chunkTDSO63CJ_js = require('./chunk-TDSO63CJ.js');
8
- var chunk2HYD2ZBK_js = require('./chunk-2HYD2ZBK.js');
9
- var chunk7UDYEFBU_js = require('./chunk-7UDYEFBU.js');
4
+ var chunkKYJROYCG_js = require('./chunk-KYJROYCG.js');
5
+ var chunkX5J5M3K3_js = require('./chunk-X5J5M3K3.js');
6
+ var chunk34Q4UM6V_js = require('./chunk-34Q4UM6V.js');
7
+ var chunkNKA6XR77_js = require('./chunk-NKA6XR77.js');
8
+ var chunkTUYHTHVV_js = require('./chunk-TUYHTHVV.js');
9
+ var chunkIWLU3VDE_js = require('./chunk-IWLU3VDE.js');
10
10
  var chunk7AOERN53_js = require('./chunk-7AOERN53.js');
11
11
  var chunkPTRF47DA_js = require('./chunk-PTRF47DA.js');
12
12
  var react = require('react');
@@ -15,11 +15,11 @@ var reactNativeWorklets = require('react-native-worklets');
15
15
 
16
16
  // src/motion/index.ts
17
17
  var Motion = {
18
- View: chunk4QGXK6TF_js.MotionView,
19
- Text: chunkZ7HIOFKQ_js.MotionText,
20
- Image: chunk3UTJJ4A3_js.MotionImage,
21
- Pressable: chunkTDSO63CJ_js.MotionPressable,
22
- ScrollView: chunk2HYD2ZBK_js.MotionScrollView
18
+ View: chunkKYJROYCG_js.MotionView,
19
+ Text: chunkX5J5M3K3_js.MotionText,
20
+ Image: chunk34Q4UM6V_js.MotionImage,
21
+ Pressable: chunkNKA6XR77_js.MotionPressable,
22
+ ScrollView: chunkTUYHTHVV_js.MotionScrollView
23
23
  };
24
24
  function useAnimation(target, transition) {
25
25
  const output = reactNativeReanimated.useSharedValue(target);
@@ -30,8 +30,26 @@ function useAnimation(target, transition) {
30
30
  const cfg = shouldReduceMotion ? { type: "no-animation" } : resolved ?? { type: "spring" };
31
31
  output.value = chunkPTRF47DA_js.resolveTransition(cfg, target);
32
32
  }, [target, cfgSig, shouldReduceMotion]);
33
+ react.useEffect(
34
+ () => () => reactNativeReanimated.cancelAnimation(output),
35
+ // `output` is identity-stable per hook instance (Reanimated guarantee).
36
+ // eslint-disable-next-line react-hooks/exhaustive-deps
37
+ []
38
+ );
33
39
  return output;
34
40
  }
41
+ function useAnimator() {
42
+ const registry = chunk7AOERN53_js.useNamedTransitions();
43
+ const shouldReduceMotion = chunk7AOERN53_js.useShouldReduceMotion();
44
+ return react.useCallback(
45
+ (value, to, transition) => {
46
+ const resolved = chunk7AOERN53_js.resolveNamedTransition(transition, registry);
47
+ const cfg = shouldReduceMotion ? { type: "no-animation" } : resolved ?? { type: "spring" };
48
+ value.value = chunkPTRF47DA_js.resolveTransition(cfg, to);
49
+ },
50
+ [registry, shouldReduceMotion]
51
+ );
52
+ }
35
53
  function useSpring(target, config) {
36
54
  const spring = resolveSpringInput(config, chunk7AOERN53_js.useNamedTransitions());
37
55
  const reanimConfig = react.useMemo(
@@ -70,6 +88,12 @@ function useSpring(target, config) {
70
88
  },
71
89
  [isSharedTarget, reanimConfig]
72
90
  );
91
+ react.useEffect(
92
+ () => () => reactNativeReanimated.cancelAnimation(output),
93
+ // `output` is identity-stable per hook instance (Reanimated guarantee).
94
+ // eslint-disable-next-line react-hooks/exhaustive-deps
95
+ []
96
+ );
73
97
  return output;
74
98
  }
75
99
  function resolveSpringInput(config, registry) {
@@ -91,6 +115,24 @@ function isSharedValue(v) {
91
115
  function useBooleanSpring(active, springConfig) {
92
116
  return useSpring(active ? 1 : 0, springConfig);
93
117
  }
118
+ function useColorCascade(rest, layers, options) {
119
+ const key = options?.key ?? "backgroundColor";
120
+ const sig = `${key}|${rest}|${layers.length}|${layers.map((l) => l.color).join(",")}`;
121
+ const colors = react.useMemo(() => layers.map((l) => l.color), [sig]);
122
+ const progressValues = react.useMemo(() => layers.map((l) => l.progress), [sig]);
123
+ return reactNativeReanimated.useAnimatedStyle(() => {
124
+ "worklet";
125
+ let acc = rest;
126
+ for (let i = 0; i < colors.length; i++) {
127
+ acc = reactNativeReanimated.interpolateColor(
128
+ progressValues[i].value,
129
+ [0, 1],
130
+ [acc, colors[i]]
131
+ );
132
+ }
133
+ return { [key]: acc };
134
+ });
135
+ }
94
136
  function useColorTransition(progress, range, options) {
95
137
  const key = options?.key ?? "backgroundColor";
96
138
  const from = range[0];
@@ -100,8 +142,139 @@ function useColorTransition(progress, range, options) {
100
142
  return { [key]: reactNativeReanimated.interpolateColor(progress.value, [0, 1], [from, to]) };
101
143
  });
102
144
  }
145
+ var TRANSFORM_KEYS = /* @__PURE__ */ new Set([
146
+ "translateX",
147
+ "translateY",
148
+ "scale",
149
+ "scaleX",
150
+ "scaleY",
151
+ "rotate",
152
+ "rotateX",
153
+ "rotateY"
154
+ ]);
155
+ var ROTATION_KEYS = /* @__PURE__ */ new Set(["rotate", "rotateX", "rotateY"]);
156
+ var COLOR_KEYS = /* @__PURE__ */ new Set([
157
+ "backgroundColor",
158
+ "color",
159
+ "borderColor",
160
+ "borderTopColor",
161
+ "borderRightColor",
162
+ "borderBottomColor",
163
+ "borderLeftColor",
164
+ "tintColor",
165
+ "shadowColor"
166
+ ]);
167
+ function evenlySpaced(count) {
168
+ if (count <= 1) return [0];
169
+ const out = [];
170
+ for (let i = 0; i < count; i++) out.push(i / (count - 1));
171
+ return out;
172
+ }
173
+ function mapExtrapolation(mode) {
174
+ if (mode === "identity") return reactNativeReanimated.Extrapolation.IDENTITY;
175
+ if (mode === "extend") return reactNativeReanimated.Extrapolation.EXTEND;
176
+ return reactNativeReanimated.Extrapolation.CLAMP;
177
+ }
178
+ function buildSignature(map, options) {
179
+ let sig = "";
180
+ for (const key of Object.keys(map)) {
181
+ const output = map[key];
182
+ sig += `${key}:${JSON.stringify(output)}|`;
183
+ }
184
+ sig += `#ir:${JSON.stringify(options?.inputRange)}|ex:${options?.extrapolate ?? ""}`;
185
+ return sig;
186
+ }
187
+ function buildEntries(map, options) {
188
+ const explicitInput = options?.inputRange;
189
+ const entries = [];
190
+ for (const key of Object.keys(map)) {
191
+ const output = map[key];
192
+ if (output === void 0 || output.length === 0) continue;
193
+ const input = explicitInput ? explicitInput : output.length === 2 ? [0, 1] : evenlySpaced(output.length);
194
+ if (__DEV__ && explicitInput && explicitInput.length !== output.length) {
195
+ console.warn(
196
+ `[inertia] useInterpolatedStyle: inputRange has ${explicitInput.length} stops but the "${String(
197
+ key
198
+ )}" output has ${output.length}. They must match \u2014 interpolation results are undefined otherwise.`
199
+ );
200
+ }
201
+ const isColor = COLOR_KEYS.has(key) && typeof output[0] === "string";
202
+ if (isColor) {
203
+ entries.push({
204
+ kind: "color",
205
+ key,
206
+ input,
207
+ output
208
+ });
209
+ } else if (ROTATION_KEYS.has(key)) {
210
+ entries.push({
211
+ kind: "rotation",
212
+ key,
213
+ input,
214
+ output
215
+ });
216
+ } else if (TRANSFORM_KEYS.has(key)) {
217
+ entries.push({
218
+ kind: "transform-numeric",
219
+ key,
220
+ input,
221
+ output
222
+ });
223
+ } else {
224
+ entries.push({
225
+ kind: "numeric",
226
+ key,
227
+ input,
228
+ output
229
+ });
230
+ }
231
+ }
232
+ return entries;
233
+ }
234
+ function useInterpolatedStyle(progress, map, options) {
235
+ const extrapolate = mapExtrapolation(options?.extrapolate);
236
+ const sig = buildSignature(map, options);
237
+ const entries = react.useMemo(() => buildEntries(map, options), [sig]);
238
+ return reactNativeReanimated.useAnimatedStyle(() => {
239
+ "worklet";
240
+ const out = {};
241
+ const transform = [];
242
+ for (const e of entries) {
243
+ if (e.kind === "color") {
244
+ out[e.key] = reactNativeReanimated.interpolateColor(progress.value, e.input, e.output);
245
+ } else if (e.kind === "numeric") {
246
+ out[e.key] = reactNativeReanimated.interpolate(progress.value, e.input, e.output, {
247
+ extrapolateLeft: extrapolate,
248
+ extrapolateRight: extrapolate
249
+ });
250
+ } else if (e.kind === "transform-numeric") {
251
+ transform.push({
252
+ [e.key]: reactNativeReanimated.interpolate(progress.value, e.input, e.output, {
253
+ extrapolateLeft: extrapolate,
254
+ extrapolateRight: extrapolate
255
+ })
256
+ });
257
+ } else {
258
+ const deg = reactNativeReanimated.interpolate(progress.value, e.input, e.output, {
259
+ extrapolateLeft: extrapolate,
260
+ extrapolateRight: extrapolate
261
+ });
262
+ transform.push({ [e.key]: `${deg}deg` });
263
+ }
264
+ }
265
+ if (transform.length > 0) out.transform = transform;
266
+ return out;
267
+ });
268
+ }
103
269
  function useMotionValue(initial) {
104
- return reactNativeReanimated.useSharedValue(initial);
270
+ const sv = reactNativeReanimated.useSharedValue(initial);
271
+ react.useEffect(
272
+ () => () => reactNativeReanimated.cancelAnimation(sv),
273
+ // `sv` is identity-stable per hook instance (Reanimated guarantee).
274
+ // eslint-disable-next-line react-hooks/exhaustive-deps
275
+ []
276
+ );
277
+ return sv;
105
278
  }
106
279
  function useTransform(arg1, inputRange, outputRange, options) {
107
280
  let producer;
@@ -124,8 +297,8 @@ function useTransform(arg1, inputRange, outputRange, options) {
124
297
  const input = inputRange;
125
298
  const output = outputRange;
126
299
  const isColor = output.length > 0 && typeof output[0] === "string";
127
- const extrapolateLeft = mapExtrapolation(options?.extrapolateLeft);
128
- const extrapolateRight = mapExtrapolation(options?.extrapolateRight);
300
+ const extrapolateLeft = mapExtrapolation2(options?.extrapolateLeft);
301
+ const extrapolateRight = mapExtrapolation2(options?.extrapolateRight);
129
302
  producer = isColor ? () => {
130
303
  "worklet";
131
304
  return reactNativeReanimated.interpolateColor(
@@ -145,7 +318,7 @@ function useTransform(arg1, inputRange, outputRange, options) {
145
318
  }
146
319
  return reactNativeReanimated.useDerivedValue(producer);
147
320
  }
148
- function mapExtrapolation(mode) {
321
+ function mapExtrapolation2(mode) {
149
322
  if (mode === "identity") return reactNativeReanimated.Extrapolation.IDENTITY;
150
323
  if (mode === "extend") return reactNativeReanimated.Extrapolation.EXTEND;
151
324
  return reactNativeReanimated.Extrapolation.CLAMP;
@@ -402,35 +575,35 @@ Object.defineProperty(exports, "useGesture", {
402
575
  });
403
576
  Object.defineProperty(exports, "MotionView", {
404
577
  enumerable: true,
405
- get: function () { return chunk4QGXK6TF_js.MotionView; }
578
+ get: function () { return chunkKYJROYCG_js.MotionView; }
406
579
  });
407
580
  Object.defineProperty(exports, "MotionText", {
408
581
  enumerable: true,
409
- get: function () { return chunkZ7HIOFKQ_js.MotionText; }
582
+ get: function () { return chunkX5J5M3K3_js.MotionText; }
410
583
  });
411
584
  Object.defineProperty(exports, "MotionImage", {
412
585
  enumerable: true,
413
- get: function () { return chunk3UTJJ4A3_js.MotionImage; }
586
+ get: function () { return chunk34Q4UM6V_js.MotionImage; }
414
587
  });
415
588
  Object.defineProperty(exports, "MotionPressable", {
416
589
  enumerable: true,
417
- get: function () { return chunkTDSO63CJ_js.MotionPressable; }
590
+ get: function () { return chunkNKA6XR77_js.MotionPressable; }
418
591
  });
419
592
  Object.defineProperty(exports, "MotionScrollView", {
420
593
  enumerable: true,
421
- get: function () { return chunk2HYD2ZBK_js.MotionScrollView; }
594
+ get: function () { return chunkTUYHTHVV_js.MotionScrollView; }
422
595
  });
423
596
  Object.defineProperty(exports, "Presence", {
424
597
  enumerable: true,
425
- get: function () { return chunk7UDYEFBU_js.Presence; }
598
+ get: function () { return chunkIWLU3VDE_js.Presence; }
426
599
  });
427
600
  Object.defineProperty(exports, "createMotionComponent", {
428
601
  enumerable: true,
429
- get: function () { return chunk7UDYEFBU_js.createMotionComponent; }
602
+ get: function () { return chunkIWLU3VDE_js.createMotionComponent; }
430
603
  });
431
604
  Object.defineProperty(exports, "usePresence", {
432
605
  enumerable: true,
433
- get: function () { return chunk7UDYEFBU_js.usePresence; }
606
+ get: function () { return chunkIWLU3VDE_js.usePresence; }
434
607
  });
435
608
  Object.defineProperty(exports, "MotionConfig", {
436
609
  enumerable: true,
@@ -474,8 +647,11 @@ Object.defineProperty(exports, "resolveTransition", {
474
647
  });
475
648
  exports.Motion = Motion;
476
649
  exports.useAnimation = useAnimation;
650
+ exports.useAnimator = useAnimator;
477
651
  exports.useBooleanSpring = useBooleanSpring;
652
+ exports.useColorCascade = useColorCascade;
478
653
  exports.useColorTransition = useColorTransition;
654
+ exports.useInterpolatedStyle = useInterpolatedStyle;
479
655
  exports.useMotionValue = useMotionValue;
480
656
  exports.useScroll = useScroll;
481
657
  exports.useShadow = useShadow;