@onlynative/inertia 0.0.1-alpha.2 → 0.0.1-alpha.3

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 (44) hide show
  1. package/README.md +29 -2
  2. package/dist/index.d.mts +2 -2
  3. package/dist/index.d.ts +2 -2
  4. package/dist/index.js +170 -58
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +171 -59
  7. package/dist/index.mjs.map +1 -1
  8. package/dist/motion/Image.d.mts +1 -1
  9. package/dist/motion/Image.d.ts +1 -1
  10. package/dist/motion/Image.js +170 -58
  11. package/dist/motion/Image.js.map +1 -1
  12. package/dist/motion/Image.mjs +171 -59
  13. package/dist/motion/Image.mjs.map +1 -1
  14. package/dist/motion/Pressable.d.mts +1 -1
  15. package/dist/motion/Pressable.d.ts +1 -1
  16. package/dist/motion/Pressable.js +170 -58
  17. package/dist/motion/Pressable.js.map +1 -1
  18. package/dist/motion/Pressable.mjs +171 -59
  19. package/dist/motion/Pressable.mjs.map +1 -1
  20. package/dist/motion/ScrollView.d.mts +1 -1
  21. package/dist/motion/ScrollView.d.ts +1 -1
  22. package/dist/motion/ScrollView.js +170 -58
  23. package/dist/motion/ScrollView.js.map +1 -1
  24. package/dist/motion/ScrollView.mjs +171 -59
  25. package/dist/motion/ScrollView.mjs.map +1 -1
  26. package/dist/motion/Text.d.mts +1 -1
  27. package/dist/motion/Text.d.ts +1 -1
  28. package/dist/motion/Text.js +170 -58
  29. package/dist/motion/Text.js.map +1 -1
  30. package/dist/motion/Text.mjs +171 -59
  31. package/dist/motion/Text.mjs.map +1 -1
  32. package/dist/motion/View.d.mts +1 -1
  33. package/dist/motion/View.d.ts +1 -1
  34. package/dist/motion/View.js +170 -58
  35. package/dist/motion/View.js.map +1 -1
  36. package/dist/motion/View.mjs +171 -59
  37. package/dist/motion/View.mjs.map +1 -1
  38. package/dist/{types-DeZZzE_e.d.mts → types-DAhX3fC2.d.mts} +40 -16
  39. package/dist/{types-DeZZzE_e.d.ts → types-DAhX3fC2.d.ts} +40 -16
  40. package/llms.txt +25 -2
  41. package/package.json +1 -1
  42. package/src/motion/createMotionComponent.tsx +258 -97
  43. package/src/motion/installCheck.ts +69 -0
  44. package/src/types.ts +44 -16
package/dist/index.mjs CHANGED
@@ -1,9 +1,14 @@
1
1
  import { Image, Pressable, ScrollView, Text, View, Platform } from 'react-native';
2
2
  import { createContext, forwardRef, useRef, useState, useEffect, useMemo, useContext, Children, isValidElement, useCallback } from 'react';
3
- import Animated, { useAnimatedStyle, useReducedMotion, useSharedValue, withSequence, runOnJS, withRepeat, withDelay, withDecay, withTiming, Easing, withSpring, isWorkletFunction } from 'react-native-reanimated';
3
+ import Animated, { useSharedValue, useAnimatedStyle, interpolateColor, useReducedMotion, withSequence, runOnJS, withRepeat, withDelay, withDecay, withTiming, Easing, withSpring, isWorkletFunction } from 'react-native-reanimated';
4
4
  import { jsx, Fragment } from 'react/jsx-runtime';
5
5
 
6
- // src/motion/Image.tsx
6
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
7
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
8
+ }) : x)(function(x) {
9
+ if (typeof require !== "undefined") return require.apply(this, arguments);
10
+ throw Error('Dynamic require of "' + x + '" is not supported');
11
+ });
7
12
  var DEFAULT_MOTION_CONFIG = {
8
13
  reducedMotion: "user"
9
14
  };
@@ -279,6 +284,40 @@ function mergeTransition(base, override) {
279
284
  }
280
285
  return { ...base ?? { type: "spring" }, ...override };
281
286
  }
287
+
288
+ // src/motion/installCheck.ts
289
+ var alreadyChecked = false;
290
+ function ensureReanimatedInstalled() {
291
+ if (!__DEV__ || alreadyChecked) return;
292
+ if (typeof process !== "undefined" && process.env?.NODE_ENV === "test") {
293
+ return;
294
+ }
295
+ alreadyChecked = true;
296
+ let version;
297
+ try {
298
+ const pkg = __require("react-native-reanimated/package.json");
299
+ version = pkg.version;
300
+ } catch {
301
+ }
302
+ if (version) {
303
+ const major = parseInt(version.split(".")[0] ?? "0", 10);
304
+ if (major < 4) {
305
+ console.error(
306
+ `[inertia] react-native-reanimated v${version} is installed, but @onlynative/inertia requires v4.0.0 or later. Upgrade with \`pnpm add react-native-reanimated@^4\` (or your package manager's equivalent).`
307
+ );
308
+ return;
309
+ }
310
+ }
311
+ const probe = function probe2() {
312
+ "worklet";
313
+ return 0;
314
+ };
315
+ if (typeof probe.__workletHash !== "number") {
316
+ console.error(
317
+ `[inertia] The Reanimated worklets babel plugin is not configured. Add \`'react-native-worklets/plugin'\` as the LAST entry in the \`plugins\` array of your \`babel.config.js\`, then restart Metro with a fresh cache: \`npx expo start -c\` or \`npx react-native start --reset-cache\`.`
318
+ );
319
+ }
320
+ }
282
321
  var TRANSFORM_KEYS = [
283
322
  "translateX",
284
323
  "translateY",
@@ -305,6 +344,14 @@ var ALL_KEYS = [
305
344
  ...COLOR_KEYS
306
345
  ];
307
346
  var TRANSFORM_KEY_SET = new Set(TRANSFORM_KEYS);
347
+ var COLOR_KEY_SET = new Set(COLOR_KEYS);
348
+ var GESTURE_LAYER_NAMES = [
349
+ "hovered",
350
+ "focused",
351
+ "focusVisible",
352
+ "pressed"
353
+ ];
354
+ var GESTURE_LAYER_NAME_SET = new Set(GESTURE_LAYER_NAMES);
308
355
  var EXITING_POINTER_EVENTS_STYLE = { pointerEvents: "none" };
309
356
  var DEFAULT_RESTING = {
310
357
  translateX: 0,
@@ -350,10 +397,18 @@ function isTopLevelTransition(t) {
350
397
  function transitionFor(prop, transition) {
351
398
  if (!transition) return void 0;
352
399
  if (isTopLevelTransition(transition)) return transition;
400
+ if (GESTURE_LAYER_NAME_SET.has(prop)) return void 0;
353
401
  return transition[prop];
354
402
  }
403
+ function gestureLayerTransitionFor(layer, transition) {
404
+ if (!transition) return void 0;
405
+ if (isTopLevelTransition(transition)) return transition;
406
+ return transition[layer];
407
+ }
355
408
  function createMotionComponent(Component) {
409
+ ensureReanimatedInstalled();
356
410
  const AnimatedComponent = Animated.createAnimatedComponent(
411
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
357
412
  Component
358
413
  );
359
414
  const Motion2 = forwardRef(function Motion3(props, ref) {
@@ -432,13 +487,19 @@ function createMotionComponent(Component) {
432
487
  }
433
488
  return initialRecord?.[key] ?? restValue(animateRecord[key]) ?? DEFAULT_RESTING[key];
434
489
  });
435
- const mergedRecord = isExiting && exitRecord ? { ...animateRecord, ...exitRecord } : mergeGestureTargets(animateRecord, gesture, {
436
- pressed,
437
- focused,
438
- focusVisible,
439
- hovered
440
- });
441
- const mergedSig = stableSig(mergedRecord) + (isExiting ? "|exit" : "") + (shouldReduceMotion ? "|rm" : "");
490
+ const pressedProgress = useSharedValue(0);
491
+ const focusedProgress = useSharedValue(0);
492
+ const focusVisibleProgress = useSharedValue(0);
493
+ const hoveredProgress = useSharedValue(0);
494
+ const gestureSV = useSharedValue(
495
+ resolveGestureLayers(gesture)
496
+ );
497
+ const gestureTargetsSig = stableSig(gesture);
498
+ useEffect(() => {
499
+ gestureSV.value = resolveGestureLayers(gesture);
500
+ }, [gestureTargetsSig]);
501
+ const baseRecord = isExiting && exitRecord ? { ...animateRecord, ...exitRecord } : animateRecord;
502
+ const baseSig = stableSig(baseRecord) + (isExiting ? "|exit" : "") + (shouldReduceMotion ? "|rm" : "");
442
503
  const transitionSig = stableSig(transition);
443
504
  const safeToRemoveRef = useRef(void 0);
444
505
  safeToRemoveRef.current = presence?.safeToRemove;
@@ -459,13 +520,13 @@ function createMotionComponent(Component) {
459
520
  };
460
521
  let transformPending = 0;
461
522
  for (const k of ALL_KEYS) {
462
- if (TRANSFORM_KEY_SET.has(k) && mergedRecord[k] !== void 0) {
523
+ if (TRANSFORM_KEY_SET.has(k) && baseRecord[k] !== void 0) {
463
524
  transformPending++;
464
525
  }
465
526
  }
466
527
  const transformGroup = transformPending > 0 ? { remaining: transformPending } : void 0;
467
528
  for (const key of ALL_KEYS) {
468
- const target = mergedRecord[key];
529
+ const target = baseRecord[key];
469
530
  if (target === void 0) continue;
470
531
  const cfg = shouldReduceMotion ? { type: "no-animation" } : transitionFor(key, transition);
471
532
  if (isExiting) pending++;
@@ -490,14 +551,76 @@ function createMotionComponent(Component) {
490
551
  if (isExiting && pending === 0) {
491
552
  safeToRemoveRef.current?.();
492
553
  }
493
- }, [mergedSig, transitionSig]);
554
+ }, [baseSig, transitionSig]);
555
+ useGestureLayerProgress(
556
+ pressedProgress,
557
+ pressed,
558
+ gesture?.pressed != null,
559
+ "pressed",
560
+ transition,
561
+ isExiting,
562
+ shouldReduceMotion
563
+ );
564
+ useGestureLayerProgress(
565
+ focusedProgress,
566
+ focused,
567
+ gesture?.focused != null,
568
+ "focused",
569
+ transition,
570
+ isExiting,
571
+ shouldReduceMotion
572
+ );
573
+ useGestureLayerProgress(
574
+ focusVisibleProgress,
575
+ focusVisible,
576
+ gesture?.focusVisible != null,
577
+ "focusVisible",
578
+ transition,
579
+ isExiting,
580
+ shouldReduceMotion
581
+ );
582
+ useGestureLayerProgress(
583
+ hoveredProgress,
584
+ hovered,
585
+ gesture?.hovered != null,
586
+ "hovered",
587
+ transition,
588
+ isExiting,
589
+ shouldReduceMotion
590
+ );
494
591
  const animatedStyle = useAnimatedStyle(() => {
495
592
  const activeKeys = activeKeysRef.current;
496
593
  const hasTransform = hasTransformRef.current;
497
594
  const out = {};
498
595
  const transform = [];
596
+ const ph = hoveredProgress.value;
597
+ const pf = focusedProgress.value;
598
+ const pfv = focusVisibleProgress.value;
599
+ const pp = pressedProgress.value;
600
+ const layers = gestureSV.value;
601
+ const hoveredLayer = layers ? layers.hovered : null;
602
+ const focusedLayer = layers ? layers.focused : null;
603
+ const focusVisibleLayer = layers ? layers.focusVisible : null;
604
+ const pressedLayer = layers ? layers.pressed : null;
499
605
  for (const key of activeKeys) {
500
- const v = sharedValues[key].value;
606
+ let v = sharedValues[key].value;
607
+ const isColor = COLOR_KEY_SET.has(key);
608
+ if (hoveredLayer && ph > 0 && hoveredLayer[key] !== void 0) {
609
+ const t = hoveredLayer[key];
610
+ v = isColor ? interpolateColor(ph, [0, 1], [v, t]) : v + (t - v) * ph;
611
+ }
612
+ if (focusedLayer && pf > 0 && focusedLayer[key] !== void 0) {
613
+ const t = focusedLayer[key];
614
+ v = isColor ? interpolateColor(pf, [0, 1], [v, t]) : v + (t - v) * pf;
615
+ }
616
+ if (focusVisibleLayer && pfv > 0 && focusVisibleLayer[key] !== void 0) {
617
+ const t = focusVisibleLayer[key];
618
+ v = isColor ? interpolateColor(pfv, [0, 1], [v, t]) : v + (t - v) * pfv;
619
+ }
620
+ if (pressedLayer && pp > 0 && pressedLayer[key] !== void 0) {
621
+ const t = pressedLayer[key];
622
+ v = isColor ? interpolateColor(pp, [0, 1], [v, t]) : v + (t - v) * pp;
623
+ }
501
624
  if (TRANSFORM_KEY_SET.has(key)) {
502
625
  transform.push(
503
626
  key === "rotate" ? { rotate: `${v}deg` } : { [key]: v }
@@ -716,52 +839,41 @@ function stableStringify(v) {
716
839
  const keys = Object.keys(obj).sort();
717
840
  return "{" + keys.map((k) => JSON.stringify(k) + ":" + stableStringify(obj[k])).join(",") + "}";
718
841
  }
719
- function mergeGestureTargets(base, gesture, active) {
720
- if (!gesture) return base;
721
- const merged = {
722
- ...base
723
- };
724
- const subStates = [
725
- gesture.hovered,
726
- gesture.focused,
727
- gesture.focusVisible,
728
- gesture.pressed
729
- ];
730
- for (const sub of subStates) {
731
- if (!sub) continue;
732
- for (const k of ALL_KEYS) {
733
- if (k in sub && !(k in merged)) {
734
- merged[k] = DEFAULT_RESTING[k];
735
- }
842
+ function resolveGestureLayers(gesture) {
843
+ if (!gesture) return null;
844
+ const out = {};
845
+ for (const layer of GESTURE_LAYER_NAMES) {
846
+ const subState = gesture[layer];
847
+ if (!subState) continue;
848
+ const resolved = {};
849
+ for (const key of ALL_KEYS) {
850
+ const raw = subState[key];
851
+ if (raw === void 0) continue;
852
+ const t = targetEndValue(raw);
853
+ if (t !== void 0) resolved[key] = t;
736
854
  }
855
+ out[layer] = resolved;
737
856
  }
738
- if (active.hovered && gesture.hovered) {
739
- Object.assign(
740
- merged,
741
- gesture.hovered
742
- );
743
- }
744
- if (active.focused && gesture.focused) {
745
- Object.assign(
746
- merged,
747
- gesture.focused
748
- );
749
- }
750
- if (active.focusVisible && gesture.focusVisible) {
751
- Object.assign(
752
- merged,
753
- gesture.focusVisible
754
- );
755
- }
756
- if (active.pressed && gesture.pressed) {
757
- Object.assign(
758
- merged,
759
- gesture.pressed
760
- );
761
- }
762
- return merged;
857
+ return out;
858
+ }
859
+ function useGestureLayerProgress(progress, active, declared, layer, transition, isExiting, shouldReduceMotion) {
860
+ const layerCfgSig = stableSig(gestureLayerTransitionFor(layer, transition));
861
+ useEffect(() => {
862
+ if (!declared) return;
863
+ if (isExiting) {
864
+ progress.value = 0;
865
+ return;
866
+ }
867
+ const target = active ? 1 : 0;
868
+ const cfg = shouldReduceMotion ? { type: "no-animation" } : gestureLayerTransitionFor(layer, transition) ?? { type: "spring" };
869
+ progress.value = resolveTransition(cfg, target);
870
+ }, [active, declared, isExiting, shouldReduceMotion, layerCfgSig]);
763
871
  }
764
872
  function useGestureHandlers(gesture, rest, setPressed, setFocused, setFocusVisible, setHovered) {
873
+ const hasPressed = gesture?.pressed ? 1 : 0;
874
+ const hasFocused = gesture?.focused ? 1 : 0;
875
+ const hasFocusVisible = gesture?.focusVisible ? 1 : 0;
876
+ const hasHovered = gesture?.hovered ? 1 : 0;
765
877
  return useMemo(() => {
766
878
  if (!gesture) return {};
767
879
  const handlers = {};
@@ -794,10 +906,10 @@ function useGestureHandlers(gesture, rest, setPressed, setFocused, setFocusVisib
794
906
  }
795
907
  return handlers;
796
908
  }, [
797
- gesture?.pressed ? 1 : 0,
798
- gesture?.focused ? 1 : 0,
799
- gesture?.focusVisible ? 1 : 0,
800
- gesture?.hovered ? 1 : 0,
909
+ hasPressed,
910
+ hasFocused,
911
+ hasFocusVisible,
912
+ hasHovered,
801
913
  rest.onTouchStart,
802
914
  rest.onTouchEnd,
803
915
  rest.onTouchCancel,