@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
@@ -9,7 +9,12 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
9
9
 
10
10
  var Animated__default = /*#__PURE__*/_interopDefault(Animated);
11
11
 
12
- // src/motion/Image.tsx
12
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
13
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
14
+ }) : x)(function(x) {
15
+ if (typeof require !== "undefined") return require.apply(this, arguments);
16
+ throw Error('Dynamic require of "' + x + '" is not supported');
17
+ });
13
18
  var DEFAULT_MOTION_CONFIG = {
14
19
  reducedMotion: "user"
15
20
  };
@@ -184,6 +189,40 @@ function mergeTransition(base, override) {
184
189
  }
185
190
  return { ...base ?? { type: "spring" }, ...override };
186
191
  }
192
+
193
+ // src/motion/installCheck.ts
194
+ var alreadyChecked = false;
195
+ function ensureReanimatedInstalled() {
196
+ if (!__DEV__ || alreadyChecked) return;
197
+ if (typeof process !== "undefined" && process.env?.NODE_ENV === "test") {
198
+ return;
199
+ }
200
+ alreadyChecked = true;
201
+ let version;
202
+ try {
203
+ const pkg = __require("react-native-reanimated/package.json");
204
+ version = pkg.version;
205
+ } catch {
206
+ }
207
+ if (version) {
208
+ const major = parseInt(version.split(".")[0] ?? "0", 10);
209
+ if (major < 4) {
210
+ console.error(
211
+ `[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).`
212
+ );
213
+ return;
214
+ }
215
+ }
216
+ const probe = function probe2() {
217
+ "worklet";
218
+ return 0;
219
+ };
220
+ if (typeof probe.__workletHash !== "number") {
221
+ console.error(
222
+ `[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\`.`
223
+ );
224
+ }
225
+ }
187
226
  var TRANSFORM_KEYS = [
188
227
  "translateX",
189
228
  "translateY",
@@ -210,6 +249,14 @@ var ALL_KEYS = [
210
249
  ...COLOR_KEYS
211
250
  ];
212
251
  var TRANSFORM_KEY_SET = new Set(TRANSFORM_KEYS);
252
+ var COLOR_KEY_SET = new Set(COLOR_KEYS);
253
+ var GESTURE_LAYER_NAMES = [
254
+ "hovered",
255
+ "focused",
256
+ "focusVisible",
257
+ "pressed"
258
+ ];
259
+ var GESTURE_LAYER_NAME_SET = new Set(GESTURE_LAYER_NAMES);
213
260
  var EXITING_POINTER_EVENTS_STYLE = { pointerEvents: "none" };
214
261
  var DEFAULT_RESTING = {
215
262
  translateX: 0,
@@ -255,10 +302,18 @@ function isTopLevelTransition(t) {
255
302
  function transitionFor(prop, transition) {
256
303
  if (!transition) return void 0;
257
304
  if (isTopLevelTransition(transition)) return transition;
305
+ if (GESTURE_LAYER_NAME_SET.has(prop)) return void 0;
258
306
  return transition[prop];
259
307
  }
308
+ function gestureLayerTransitionFor(layer, transition) {
309
+ if (!transition) return void 0;
310
+ if (isTopLevelTransition(transition)) return transition;
311
+ return transition[layer];
312
+ }
260
313
  function createMotionComponent(Component) {
314
+ ensureReanimatedInstalled();
261
315
  const AnimatedComponent = Animated__default.default.createAnimatedComponent(
316
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
262
317
  Component
263
318
  );
264
319
  const Motion = react.forwardRef(function Motion2(props, ref) {
@@ -337,13 +392,19 @@ function createMotionComponent(Component) {
337
392
  }
338
393
  return initialRecord?.[key] ?? restValue(animateRecord[key]) ?? DEFAULT_RESTING[key];
339
394
  });
340
- const mergedRecord = isExiting && exitRecord ? { ...animateRecord, ...exitRecord } : mergeGestureTargets(animateRecord, gesture, {
341
- pressed,
342
- focused,
343
- focusVisible,
344
- hovered
345
- });
346
- const mergedSig = stableSig(mergedRecord) + (isExiting ? "|exit" : "") + (shouldReduceMotion ? "|rm" : "");
395
+ const pressedProgress = Animated.useSharedValue(0);
396
+ const focusedProgress = Animated.useSharedValue(0);
397
+ const focusVisibleProgress = Animated.useSharedValue(0);
398
+ const hoveredProgress = Animated.useSharedValue(0);
399
+ const gestureSV = Animated.useSharedValue(
400
+ resolveGestureLayers(gesture)
401
+ );
402
+ const gestureTargetsSig = stableSig(gesture);
403
+ react.useEffect(() => {
404
+ gestureSV.value = resolveGestureLayers(gesture);
405
+ }, [gestureTargetsSig]);
406
+ const baseRecord = isExiting && exitRecord ? { ...animateRecord, ...exitRecord } : animateRecord;
407
+ const baseSig = stableSig(baseRecord) + (isExiting ? "|exit" : "") + (shouldReduceMotion ? "|rm" : "");
347
408
  const transitionSig = stableSig(transition);
348
409
  const safeToRemoveRef = react.useRef(void 0);
349
410
  safeToRemoveRef.current = presence?.safeToRemove;
@@ -364,13 +425,13 @@ function createMotionComponent(Component) {
364
425
  };
365
426
  let transformPending = 0;
366
427
  for (const k of ALL_KEYS) {
367
- if (TRANSFORM_KEY_SET.has(k) && mergedRecord[k] !== void 0) {
428
+ if (TRANSFORM_KEY_SET.has(k) && baseRecord[k] !== void 0) {
368
429
  transformPending++;
369
430
  }
370
431
  }
371
432
  const transformGroup = transformPending > 0 ? { remaining: transformPending } : void 0;
372
433
  for (const key of ALL_KEYS) {
373
- const target = mergedRecord[key];
434
+ const target = baseRecord[key];
374
435
  if (target === void 0) continue;
375
436
  const cfg = shouldReduceMotion ? { type: "no-animation" } : transitionFor(key, transition);
376
437
  if (isExiting) pending++;
@@ -395,14 +456,76 @@ function createMotionComponent(Component) {
395
456
  if (isExiting && pending === 0) {
396
457
  safeToRemoveRef.current?.();
397
458
  }
398
- }, [mergedSig, transitionSig]);
459
+ }, [baseSig, transitionSig]);
460
+ useGestureLayerProgress(
461
+ pressedProgress,
462
+ pressed,
463
+ gesture?.pressed != null,
464
+ "pressed",
465
+ transition,
466
+ isExiting,
467
+ shouldReduceMotion
468
+ );
469
+ useGestureLayerProgress(
470
+ focusedProgress,
471
+ focused,
472
+ gesture?.focused != null,
473
+ "focused",
474
+ transition,
475
+ isExiting,
476
+ shouldReduceMotion
477
+ );
478
+ useGestureLayerProgress(
479
+ focusVisibleProgress,
480
+ focusVisible,
481
+ gesture?.focusVisible != null,
482
+ "focusVisible",
483
+ transition,
484
+ isExiting,
485
+ shouldReduceMotion
486
+ );
487
+ useGestureLayerProgress(
488
+ hoveredProgress,
489
+ hovered,
490
+ gesture?.hovered != null,
491
+ "hovered",
492
+ transition,
493
+ isExiting,
494
+ shouldReduceMotion
495
+ );
399
496
  const animatedStyle = Animated.useAnimatedStyle(() => {
400
497
  const activeKeys = activeKeysRef.current;
401
498
  const hasTransform = hasTransformRef.current;
402
499
  const out = {};
403
500
  const transform = [];
501
+ const ph = hoveredProgress.value;
502
+ const pf = focusedProgress.value;
503
+ const pfv = focusVisibleProgress.value;
504
+ const pp = pressedProgress.value;
505
+ const layers = gestureSV.value;
506
+ const hoveredLayer = layers ? layers.hovered : null;
507
+ const focusedLayer = layers ? layers.focused : null;
508
+ const focusVisibleLayer = layers ? layers.focusVisible : null;
509
+ const pressedLayer = layers ? layers.pressed : null;
404
510
  for (const key of activeKeys) {
405
- const v = sharedValues[key].value;
511
+ let v = sharedValues[key].value;
512
+ const isColor = COLOR_KEY_SET.has(key);
513
+ if (hoveredLayer && ph > 0 && hoveredLayer[key] !== void 0) {
514
+ const t = hoveredLayer[key];
515
+ v = isColor ? Animated.interpolateColor(ph, [0, 1], [v, t]) : v + (t - v) * ph;
516
+ }
517
+ if (focusedLayer && pf > 0 && focusedLayer[key] !== void 0) {
518
+ const t = focusedLayer[key];
519
+ v = isColor ? Animated.interpolateColor(pf, [0, 1], [v, t]) : v + (t - v) * pf;
520
+ }
521
+ if (focusVisibleLayer && pfv > 0 && focusVisibleLayer[key] !== void 0) {
522
+ const t = focusVisibleLayer[key];
523
+ v = isColor ? Animated.interpolateColor(pfv, [0, 1], [v, t]) : v + (t - v) * pfv;
524
+ }
525
+ if (pressedLayer && pp > 0 && pressedLayer[key] !== void 0) {
526
+ const t = pressedLayer[key];
527
+ v = isColor ? Animated.interpolateColor(pp, [0, 1], [v, t]) : v + (t - v) * pp;
528
+ }
406
529
  if (TRANSFORM_KEY_SET.has(key)) {
407
530
  transform.push(
408
531
  key === "rotate" ? { rotate: `${v}deg` } : { [key]: v }
@@ -621,52 +744,41 @@ function stableStringify(v) {
621
744
  const keys = Object.keys(obj).sort();
622
745
  return "{" + keys.map((k) => JSON.stringify(k) + ":" + stableStringify(obj[k])).join(",") + "}";
623
746
  }
624
- function mergeGestureTargets(base, gesture, active) {
625
- if (!gesture) return base;
626
- const merged = {
627
- ...base
628
- };
629
- const subStates = [
630
- gesture.hovered,
631
- gesture.focused,
632
- gesture.focusVisible,
633
- gesture.pressed
634
- ];
635
- for (const sub of subStates) {
636
- if (!sub) continue;
637
- for (const k of ALL_KEYS) {
638
- if (k in sub && !(k in merged)) {
639
- merged[k] = DEFAULT_RESTING[k];
640
- }
747
+ function resolveGestureLayers(gesture) {
748
+ if (!gesture) return null;
749
+ const out = {};
750
+ for (const layer of GESTURE_LAYER_NAMES) {
751
+ const subState = gesture[layer];
752
+ if (!subState) continue;
753
+ const resolved = {};
754
+ for (const key of ALL_KEYS) {
755
+ const raw = subState[key];
756
+ if (raw === void 0) continue;
757
+ const t = targetEndValue(raw);
758
+ if (t !== void 0) resolved[key] = t;
641
759
  }
760
+ out[layer] = resolved;
642
761
  }
643
- if (active.hovered && gesture.hovered) {
644
- Object.assign(
645
- merged,
646
- gesture.hovered
647
- );
648
- }
649
- if (active.focused && gesture.focused) {
650
- Object.assign(
651
- merged,
652
- gesture.focused
653
- );
654
- }
655
- if (active.focusVisible && gesture.focusVisible) {
656
- Object.assign(
657
- merged,
658
- gesture.focusVisible
659
- );
660
- }
661
- if (active.pressed && gesture.pressed) {
662
- Object.assign(
663
- merged,
664
- gesture.pressed
665
- );
666
- }
667
- return merged;
762
+ return out;
763
+ }
764
+ function useGestureLayerProgress(progress, active, declared, layer, transition, isExiting, shouldReduceMotion) {
765
+ const layerCfgSig = stableSig(gestureLayerTransitionFor(layer, transition));
766
+ react.useEffect(() => {
767
+ if (!declared) return;
768
+ if (isExiting) {
769
+ progress.value = 0;
770
+ return;
771
+ }
772
+ const target = active ? 1 : 0;
773
+ const cfg = shouldReduceMotion ? { type: "no-animation" } : gestureLayerTransitionFor(layer, transition) ?? { type: "spring" };
774
+ progress.value = resolveTransition(cfg, target);
775
+ }, [active, declared, isExiting, shouldReduceMotion, layerCfgSig]);
668
776
  }
669
777
  function useGestureHandlers(gesture, rest, setPressed, setFocused, setFocusVisible, setHovered) {
778
+ const hasPressed = gesture?.pressed ? 1 : 0;
779
+ const hasFocused = gesture?.focused ? 1 : 0;
780
+ const hasFocusVisible = gesture?.focusVisible ? 1 : 0;
781
+ const hasHovered = gesture?.hovered ? 1 : 0;
670
782
  return react.useMemo(() => {
671
783
  if (!gesture) return {};
672
784
  const handlers = {};
@@ -699,10 +811,10 @@ function useGestureHandlers(gesture, rest, setPressed, setFocused, setFocusVisib
699
811
  }
700
812
  return handlers;
701
813
  }, [
702
- gesture?.pressed ? 1 : 0,
703
- gesture?.focused ? 1 : 0,
704
- gesture?.focusVisible ? 1 : 0,
705
- gesture?.hovered ? 1 : 0,
814
+ hasPressed,
815
+ hasFocused,
816
+ hasFocusVisible,
817
+ hasHovered,
706
818
  rest.onTouchStart,
707
819
  rest.onTouchEnd,
708
820
  rest.onTouchCancel,