@rootnative/inertia 0.0.9 → 0.0.10

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 (100) hide show
  1. package/CHANGELOG.md +68 -1
  2. package/README.md +7 -7
  3. package/dist/applyBounds-BYGiHrYO.d.mts +18 -0
  4. package/dist/applyBounds-BYGiHrYO.d.ts +18 -0
  5. package/dist/{chunk-E3ALFSH2.js → chunk-2UGWAB6N.js} +78 -70
  6. package/dist/{chunk-ZBHQPVWE.js → chunk-3ZNHPT5Z.js} +2 -2
  7. package/dist/{chunk-IHVMNOS4.js → chunk-46766TBM.js} +2 -2
  8. package/dist/{chunk-MUT6BTZS.js → chunk-4EZ5DBL3.js} +10 -7
  9. package/dist/{chunk-MFAFB4K7.mjs → chunk-6FCATUMY.mjs} +8 -10
  10. package/dist/{chunk-6YIUETBF.mjs → chunk-7BH3CAO5.mjs} +1 -1
  11. package/dist/{chunk-JBK5ZLMH.mjs → chunk-CUHOCONB.mjs} +1 -1
  12. package/dist/{chunk-M4766VUV.mjs → chunk-DRA2K53O.mjs} +1 -1
  13. package/dist/{chunk-L4JFECXU.mjs → chunk-F4HMCXAX.mjs} +6 -3
  14. package/dist/{chunk-W7NTRSPD.mjs → chunk-HEAWMZEM.mjs} +105 -66
  15. package/dist/{chunk-IX6SEOSK.mjs → chunk-JENYDTXH.mjs} +52 -44
  16. package/dist/chunk-KFHZMFAX.js +23 -0
  17. package/dist/{chunk-6AN5X3YE.js → chunk-KXU6VH2Y.js} +10 -11
  18. package/dist/{chunk-WNVHPMBI.js → chunk-N33GSDNQ.js} +106 -65
  19. package/dist/chunk-OH46TGEA.mjs +20 -0
  20. package/dist/{chunk-QNLSCOR5.mjs → chunk-OLOSU2BD.mjs} +1 -1
  21. package/dist/chunk-PLKXCJIB.js +8 -0
  22. package/dist/{chunk-GSUC4HWP.mjs → chunk-QXKPIENP.mjs} +1 -1
  23. package/dist/chunk-UBHQJFUW.js +8 -0
  24. package/dist/{chunk-6NOCY764.js → chunk-VKXSL3ZL.js} +2 -2
  25. package/dist/chunk-XKNEQDAT.js +8 -0
  26. package/dist/{chunk-EN4PN7X3.mjs → chunk-Z23AMUSW.mjs} +1 -1
  27. package/dist/gestureLayer/index.d.mts +3 -3
  28. package/dist/gestureLayer/index.d.ts +3 -3
  29. package/dist/gestureLayer/index.js +12 -18
  30. package/dist/gestureLayer/index.mjs +5 -11
  31. package/dist/index.d.mts +87 -45
  32. package/dist/index.d.ts +87 -45
  33. package/dist/index.js +114 -91
  34. package/dist/index.mjs +66 -59
  35. package/dist/motion/FlatList.d.mts +1 -1
  36. package/dist/motion/FlatList.d.ts +1 -1
  37. package/dist/motion/FlatList.js +5 -5
  38. package/dist/motion/FlatList.mjs +4 -4
  39. package/dist/motion/Image.d.mts +1 -1
  40. package/dist/motion/Image.d.ts +1 -1
  41. package/dist/motion/Image.js +5 -5
  42. package/dist/motion/Image.mjs +4 -4
  43. package/dist/motion/Pressable.d.mts +1 -1
  44. package/dist/motion/Pressable.d.ts +1 -1
  45. package/dist/motion/Pressable.js +5 -5
  46. package/dist/motion/Pressable.mjs +4 -4
  47. package/dist/motion/ScrollView.d.mts +1 -1
  48. package/dist/motion/ScrollView.d.ts +1 -1
  49. package/dist/motion/ScrollView.js +5 -5
  50. package/dist/motion/ScrollView.mjs +4 -4
  51. package/dist/motion/Text.d.mts +1 -1
  52. package/dist/motion/Text.d.ts +1 -1
  53. package/dist/motion/Text.js +5 -5
  54. package/dist/motion/Text.mjs +4 -4
  55. package/dist/motion/View.d.mts +1 -1
  56. package/dist/motion/View.d.ts +1 -1
  57. package/dist/motion/View.js +5 -5
  58. package/dist/motion/View.mjs +4 -4
  59. package/dist/touch/index.d.mts +2 -1
  60. package/dist/touch/index.d.ts +2 -1
  61. package/dist/touch/index.js +16 -31
  62. package/dist/touch/index.mjs +11 -29
  63. package/dist/{types-DyJpG64F.d.mts → types-08mG8fNk.d.mts} +10 -3
  64. package/dist/{types-DyJpG64F.d.ts → types-08mG8fNk.d.ts} +10 -3
  65. package/dist/{useGesture-DbH46EBp.d.ts → useGesture-D1lHeQQ6.d.ts} +1 -1
  66. package/dist/{useGesture-CnZQnYHH.d.mts → useGesture-DjszaHWz.d.mts} +1 -1
  67. package/package.json +4 -2
  68. package/src/config/namedTransitions.ts +7 -9
  69. package/src/gestureLayer/index.ts +3 -0
  70. package/src/gestureLayer/useGestureLayer.ts +6 -9
  71. package/src/gestures/focusVisibility.ts +19 -17
  72. package/src/gestures/index.ts +1 -1
  73. package/src/index.ts +9 -0
  74. package/src/layout/resolveLayout.ts +4 -1
  75. package/src/layout/useSharedLayout.ts +2 -1
  76. package/src/motion/createMotionComponent.tsx +92 -44
  77. package/src/presence/Presence.tsx +5 -7
  78. package/src/touch/applyBounds.ts +30 -0
  79. package/src/touch/index.ts +1 -0
  80. package/src/touch/useTouchDrag.ts +15 -45
  81. package/src/transitions/constants.ts +14 -0
  82. package/src/transitions/easing.ts +23 -11
  83. package/src/transitions/index.ts +5 -0
  84. package/src/transitions/keys.ts +0 -2
  85. package/src/transitions/resolve.ts +86 -11
  86. package/src/transitions/resolveSequence.ts +3 -1
  87. package/src/transitions/runtime.ts +4 -7
  88. package/src/transitions/spring.ts +7 -2
  89. package/src/types.ts +9 -2
  90. package/src/values/extrapolation.ts +21 -0
  91. package/src/values/index.ts +1 -0
  92. package/src/values/useGesture.ts +9 -2
  93. package/src/values/useInterpolatedStyle.ts +5 -12
  94. package/src/values/useShadow.ts +18 -7
  95. package/src/values/useSpring.ts +34 -25
  96. package/src/values/useTransform.ts +24 -20
  97. package/src/values/useTranslateStyle.ts +31 -0
  98. package/dist/chunk-24NUL23E.js +0 -8
  99. package/dist/chunk-4XBX7KOD.js +0 -8
  100. package/dist/chunk-Z5USXWTE.js +0 -8
@@ -1,7 +1,9 @@
1
- import { buildReleaseAnimation } from '../chunk-W7NTRSPD.mjs';
2
- import { useMemo } from 'react';
1
+ import { applyBounds, useTranslateStyle } from '../chunk-OH46TGEA.mjs';
2
+ export { applyBounds } from '../chunk-OH46TGEA.mjs';
3
+ import { buildReleaseAnimation } from '../chunk-HEAWMZEM.mjs';
4
+ import { useRef, useMemo } from 'react';
3
5
  import { PanResponder } from 'react-native';
4
- import { useSharedValue, useAnimatedStyle } from 'react-native-reanimated';
6
+ import { useSharedValue } from 'react-native-reanimated';
5
7
 
6
8
  function useTouchDrag(options = {}) {
7
9
  const { axis = "both", constraints, elastic = 0 } = options;
@@ -17,22 +19,12 @@ function useTouchDrag(options = {}) {
17
19
  const top = constraints?.top;
18
20
  const bottom = constraints?.bottom;
19
21
  const elasticCoef = elastic;
20
- const { onDragStart, onDragEnd, onRelease } = options;
22
+ const callbacksRef = useRef(options);
23
+ callbacksRef.current = options;
21
24
  const responder = useMemo(
22
25
  () => buildResponder(),
23
26
  // eslint-disable-next-line react-hooks/exhaustive-deps
24
- [
25
- lockX,
26
- lockY,
27
- left,
28
- right,
29
- top,
30
- bottom,
31
- elasticCoef,
32
- onDragStart,
33
- onDragEnd,
34
- onRelease
35
- ]
27
+ [lockX, lockY, left, right, top, bottom, elasticCoef]
36
28
  );
37
29
  function buildResponder() {
38
30
  const handleEnd = (g) => {
@@ -41,6 +33,7 @@ function useTouchDrag(options = {}) {
41
33
  const y = dragY.value;
42
34
  const vx = g.vx * 1e3;
43
35
  const vy = g.vy * 1e3;
36
+ const { onRelease, onDragEnd } = callbacksRef.current;
44
37
  if (onRelease) {
45
38
  const result = onRelease({ x, y, velocity: { x: vx, y: vy } });
46
39
  if (result) {
@@ -72,7 +65,7 @@ function useTouchDrag(options = {}) {
72
65
  startX.value = dragX.value;
73
66
  startY.value = dragY.value;
74
67
  isDragging.value = true;
75
- if (onDragStart) onDragStart();
68
+ callbacksRef.current.onDragStart?.();
76
69
  },
77
70
  onPanResponderMove: (_e, g) => {
78
71
  if (lockX) {
@@ -96,9 +89,7 @@ function useTouchDrag(options = {}) {
96
89
  onPanResponderTerminate: (_e, g) => handleEnd(g)
97
90
  });
98
91
  }
99
- const animatedStyle = useAnimatedStyle(() => ({
100
- transform: [{ translateX: dragX.value }, { translateY: dragY.value }]
101
- }));
92
+ const animatedStyle = useTranslateStyle(dragX, dragY);
102
93
  return {
103
94
  panHandlers: responder.panHandlers,
104
95
  animatedStyle,
@@ -107,14 +98,5 @@ function useTouchDrag(options = {}) {
107
98
  isDragging
108
99
  };
109
100
  }
110
- function applyBounds(value, min, max, elastic) {
111
- if (min !== void 0 && value < min) {
112
- return elastic > 0 ? min + (value - min) * elastic : min;
113
- }
114
- if (max !== void 0 && value > max) {
115
- return elastic > 0 ? max + (value - max) * elastic : max;
116
- }
117
- return value;
118
- }
119
101
 
120
102
  export { useTouchDrag };
@@ -24,8 +24,6 @@ interface SpringTransition {
24
24
  friction?: number;
25
25
  mass?: number;
26
26
  velocity?: number;
27
- restSpeedThreshold?: number;
28
- restDisplacementThreshold?: number;
29
27
  delay?: number;
30
28
  repeat?: RepeatConfig;
31
29
  }
@@ -107,6 +105,15 @@ type NamedTransitions = Partial<Record<TransitionName, TransitionConfig>>;
107
105
  type TransitionInput = TransitionConfig | TransitionName;
108
106
  /**
109
107
  * Repeat config — one shape, not three flags. Default `alternate: true`.
108
+ *
109
+ * `count` is the total number of iterations, including the first pass, so
110
+ * `repeat: 2` plays the animation twice. A count below `1` runs the animation
111
+ * once and warns in dev.
112
+ *
113
+ * `alternate` reverses direction on every other pass for a single-value
114
+ * animation. It has no effect on a sequence (an array target): Reanimated
115
+ * restarts a sequence at its first step on every pass. Append the reverse
116
+ * steps to the sequence to alternate.
110
117
  */
111
118
  type RepeatConfig = number | 'infinite' | {
112
119
  count: number | 'infinite';
@@ -456,4 +463,4 @@ interface MotionComponent<C extends ComponentType<any>> {
456
463
  displayName?: string;
457
464
  }
458
465
 
459
- export type { AnimatableValue as A, BoxShadowInput as B, DecayTransition as D, EasingInput as E, GestureLayerTransitions as G, MotionComponent as M, NamedTransitions as N, PerPropertyTransition as P, RegisteredTransitions as R, SpringTransition as S, TransitionConfig as T, VariantsMap as V, MotionProps as a, TransitionInput as b, TransitionName as c, VariantController as d, AnimateStyle as e, AnimationCallbackInfo as f, EasingFunction as g, EasingFunctionFactory as h, GestureSubStates as i, NoAnimationTransition as j, RepeatConfig as k, SequenceStep as l, TimingTransition as m, Transition as n };
466
+ export type { AnimatableValue as A, BoxShadowInput as B, DecayTransition as D, EasingInput as E, GestureLayerTransitions as G, MotionComponent as M, NamedTransitions as N, PerPropertyTransition as P, RegisteredTransitions as R, SpringTransition as S, TransitionConfig as T, VariantsMap as V, MotionProps as a, TransitionInput as b, TransitionName as c, VariantController as d, AnimateStyle as e, AnimationCallbackInfo as f, EasingFunction as g, EasingFunctionFactory as h, GestureSubStates as i, MotionComponentProps as j, NoAnimationTransition as k, RepeatConfig as l, SequenceStep as m, TimingTransition as n, Transition as o };
@@ -24,8 +24,6 @@ interface SpringTransition {
24
24
  friction?: number;
25
25
  mass?: number;
26
26
  velocity?: number;
27
- restSpeedThreshold?: number;
28
- restDisplacementThreshold?: number;
29
27
  delay?: number;
30
28
  repeat?: RepeatConfig;
31
29
  }
@@ -107,6 +105,15 @@ type NamedTransitions = Partial<Record<TransitionName, TransitionConfig>>;
107
105
  type TransitionInput = TransitionConfig | TransitionName;
108
106
  /**
109
107
  * Repeat config — one shape, not three flags. Default `alternate: true`.
108
+ *
109
+ * `count` is the total number of iterations, including the first pass, so
110
+ * `repeat: 2` plays the animation twice. A count below `1` runs the animation
111
+ * once and warns in dev.
112
+ *
113
+ * `alternate` reverses direction on every other pass for a single-value
114
+ * animation. It has no effect on a sequence (an array target): Reanimated
115
+ * restarts a sequence at its first step on every pass. Append the reverse
116
+ * steps to the sequence to alternate.
110
117
  */
111
118
  type RepeatConfig = number | 'infinite' | {
112
119
  count: number | 'infinite';
@@ -456,4 +463,4 @@ interface MotionComponent<C extends ComponentType<any>> {
456
463
  displayName?: string;
457
464
  }
458
465
 
459
- export type { AnimatableValue as A, BoxShadowInput as B, DecayTransition as D, EasingInput as E, GestureLayerTransitions as G, MotionComponent as M, NamedTransitions as N, PerPropertyTransition as P, RegisteredTransitions as R, SpringTransition as S, TransitionConfig as T, VariantsMap as V, MotionProps as a, TransitionInput as b, TransitionName as c, VariantController as d, AnimateStyle as e, AnimationCallbackInfo as f, EasingFunction as g, EasingFunctionFactory as h, GestureSubStates as i, NoAnimationTransition as j, RepeatConfig as k, SequenceStep as l, TimingTransition as m, Transition as n };
466
+ export type { AnimatableValue as A, BoxShadowInput as B, DecayTransition as D, EasingInput as E, GestureLayerTransitions as G, MotionComponent as M, NamedTransitions as N, PerPropertyTransition as P, RegisteredTransitions as R, SpringTransition as S, TransitionConfig as T, VariantsMap as V, MotionProps as a, TransitionInput as b, TransitionName as c, VariantController as d, AnimateStyle as e, AnimationCallbackInfo as f, EasingFunction as g, EasingFunctionFactory as h, GestureSubStates as i, MotionComponentProps as j, NoAnimationTransition as k, RepeatConfig as l, SequenceStep as m, TimingTransition as n, Transition as o };
@@ -1,5 +1,5 @@
1
1
  import { SharedValue } from 'react-native-reanimated';
2
- import { b as TransitionInput, G as GestureLayerTransitions } from './types-DyJpG64F.js';
2
+ import { b as TransitionInput, G as GestureLayerTransitions } from './types-08mG8fNk.js';
3
3
 
4
4
  /**
5
5
  * Handler bag returned by `useGesture`. Spread on a `Pressable` to drive the
@@ -1,5 +1,5 @@
1
1
  import { SharedValue } from 'react-native-reanimated';
2
- import { b as TransitionInput, G as GestureLayerTransitions } from './types-DyJpG64F.mjs';
2
+ import { b as TransitionInput, G as GestureLayerTransitions } from './types-08mG8fNk.mjs';
3
3
 
4
4
  /**
5
5
  * Handler bag returned by `useGesture`. Spread on a `Pressable` to drive the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rootnative/inertia",
3
- "version": "0.0.9",
3
+ "version": "0.0.10",
4
4
  "description": "Declarative animation primitives for React Native, built on react-native-reanimated.",
5
5
  "license": "MIT",
6
6
  "author": "RootNative",
@@ -125,13 +125,14 @@
125
125
  "!**/*.test.*"
126
126
  ],
127
127
  "peerDependencies": {
128
+ "@testing-library/react-native": ">=13.0.0",
128
129
  "react": ">=19.0.0",
129
130
  "react-native": ">=0.81.0",
130
131
  "react-native-reanimated": ">=4.0.0",
131
132
  "react-native-worklets": ">=0.5.0"
132
133
  },
133
134
  "peerDependenciesMeta": {
134
- "react-native-worklets": {
135
+ "@testing-library/react-native": {
135
136
  "optional": true
136
137
  }
137
138
  },
@@ -145,6 +146,7 @@
145
146
  "react": "19.1.0",
146
147
  "react-native": "0.81.5",
147
148
  "react-native-reanimated": "~4.1.1",
149
+ "react-native-worklets": "~0.5.1",
148
150
  "react-test-renderer": "19.1.0",
149
151
  "size-limit": "^11.1.0",
150
152
  "tsup": "^8.3.5",
@@ -1,3 +1,4 @@
1
+ import { warnOnce } from '../internal/warnOnce'
1
2
  import { isTopLevelTransition } from '../transitions/keys'
2
3
  import {
3
4
  type NamedTransitions,
@@ -6,8 +7,6 @@ import {
6
7
  type TransitionInput,
7
8
  } from '../types'
8
9
 
9
- declare const __DEV__: boolean
10
-
11
10
  /**
12
11
  * Fallback used when a name isn't found in the registry: the library default
13
12
  * spring, matching what an omitted transition resolves to everywhere else.
@@ -26,13 +25,12 @@ export function lookupNamedTransition(
26
25
  ): TransitionConfig {
27
26
  const cfg = registry[name]
28
27
  if (cfg) return cfg
29
- if (__DEV__) {
30
- console.warn(
31
- `[inertia] Unknown transition name "${name}" — falling back to the ` +
32
- `default spring. Register it on a provider: ` +
33
- `<MotionConfig transitions={{ '${name}': { ... } }}>.`,
34
- )
35
- }
28
+ warnOnce(
29
+ `unknown-transition:${name}`,
30
+ `[inertia] Unknown transition name "${name}" — falling back to the ` +
31
+ `default spring. Register it on a provider: ` +
32
+ `<MotionConfig transitions={{ '${name}': { ... } }}>.`,
33
+ )
36
34
  return UNKNOWN_NAME_FALLBACK
37
35
  }
38
36
 
@@ -20,3 +20,6 @@ export type {
20
20
  UseGestureLayerOptions,
21
21
  UseGestureLayerResult,
22
22
  } from './useGestureLayer'
23
+ // The per-layer form of `UseGestureLayerOptions.transition`. Re-exported here
24
+ // so a consumer of this subpath can name it without also importing the root.
25
+ export type { GestureLayerTransitions } from '../types'
@@ -210,7 +210,10 @@ export function useGestureLayer(
210
210
  // JS-thread precompute: union of keys across all layers, per-key type
211
211
  // (number vs color), and a rest-fallback table. The worklet body reads
212
212
  // from `meta` instead of probing each layer per frame — the type check
213
- // only runs when layer identities change.
213
+ // only runs when the layers change structurally. Keyed on a signature, not
214
+ // on object identity: `states` is usually an inline literal, and a fresh
215
+ // `meta` each render would rebuild the animated style's worklet.
216
+ const statesSig = stableSig(states)
214
217
  const meta = useMemo(() => {
215
218
  const layers = {
216
219
  rest: states.rest,
@@ -251,14 +254,8 @@ export function useGestureLayer(
251
254
  restRaw !== undefined ? restRaw : isColor ? 'transparent' : 0
252
255
  }
253
256
  return { layers, keys, types, restValues }
254
- }, [
255
- states.rest,
256
- states.hovered,
257
- states.focused,
258
- states.focusVisible,
259
- states.pressed,
260
- states.disabled,
261
- ])
257
+ // eslint-disable-next-line react-hooks/exhaustive-deps
258
+ }, [statesSig])
262
259
 
263
260
  const style = useAnimatedStyle(() => {
264
261
  const { layers, keys, types, restValues } = meta
@@ -12,15 +12,16 @@ import { Platform } from 'react-native'
12
12
  * arrives via D-pad, screen reader, or hardware keyboard, all of which are
13
13
  * keyboard-equivalent — so `isFocusVisible()` is unconditionally `true`.
14
14
  *
15
- * The web listeners attach eagerly at module import (capture phase, so they
16
- * run before the focus event reaches the focused element) and stay installed
17
- * for the lifetime of the document. Eager installation matters: the very
18
- * first interaction with a page can be the mouse click that focuses a
19
- * gesture-wired element, and if the listeners only attached during that
20
- * focus dispatch the mousedown would already have passed unobserved
21
- * leaving the default `'keyboard'` modality and drawing a focus ring for a
22
- * pointer interaction. They are passive and idle-cheap; the cost is one
23
- * boolean read per `onFocus` dispatch.
15
+ * The web listeners attach when the first component that tracks
16
+ * `focusVisible` mounts (`installFocusVisibility`, called from a mount
17
+ * effect), in the capture phase so they run before the focus event reaches
18
+ * the focused element, and they stay installed for the lifetime of the
19
+ * document. Mount-time installation is early enough: the click that focuses
20
+ * a gesture-wired element can only land on an element that is already
21
+ * mounted, so its `mousedown` is observed. The listeners are not attached at
22
+ * import time `@rootnative/inertia` declares `sideEffects: false`, and an
23
+ * import-time listener would make that declaration false. They are passive
24
+ * and idle-cheap; the cost is one boolean read per `onFocus` dispatch.
24
25
  */
25
26
 
26
27
  type InputModality = 'keyboard' | 'pointer'
@@ -38,7 +39,14 @@ function setPointer() {
38
39
  modality = 'pointer'
39
40
  }
40
41
 
41
- function ensureInstalled(): void {
42
+ /**
43
+ * Attach the document listeners that track input modality on web. Idempotent
44
+ * and a no-op on native or without a `document`. Call it from a mount effect
45
+ * of any component that reads `isFocusVisible()`, so the pointer event that
46
+ * precedes the first focus is observed (see module doc above).
47
+ * `isFocusVisible` also calls it as a safety net.
48
+ */
49
+ export function installFocusVisibility(): void {
42
50
  if (installed) return
43
51
  if (Platform.OS !== 'web') return
44
52
  if (typeof document === 'undefined') return
@@ -49,12 +57,6 @@ function ensureInstalled(): void {
49
57
  installed = true
50
58
  }
51
59
 
52
- // Install at import time so the pointer event that precedes the first focus
53
- // is observed (see module doc above). `ensureInstalled` stays in
54
- // `isFocusVisible` as a safety net for environments where `document` appears
55
- // after import.
56
- ensureInstalled()
57
-
58
60
  /**
59
61
  * `true` if the next `onFocus` should be treated as "focus-visible" (keyboard
60
62
  * focus). On native, always `true`. On web, reflects the most recent user
@@ -62,7 +64,7 @@ ensureInstalled()
62
64
  */
63
65
  export function isFocusVisible(): boolean {
64
66
  if (Platform.OS !== 'web') return true
65
- ensureInstalled()
67
+ installFocusVisibility()
66
68
  return modality === 'keyboard'
67
69
  }
68
70
 
@@ -1 +1 @@
1
- export { isFocusVisible } from './focusVisibility'
1
+ export { installFocusVisibility, isFocusVisible } from './focusVisibility'
package/src/index.ts CHANGED
@@ -42,12 +42,18 @@ export {
42
42
  resolveTransition,
43
43
  resolveAnimatableValue,
44
44
  ensureWorkletEasing,
45
+ isTopLevelTransition,
46
+ stableSig,
45
47
  type AnimationCallback,
48
+ type CallbackFactory,
46
49
  } from './transitions'
47
50
  // Seed value for any color shared value a custom animated component drives
48
51
  // through `resolveTransition`. Exported because the obvious choice —
49
52
  // `'transparent'` — cannot be animated away from; see the symbol's own docs.
50
53
  export { TRANSPARENT } from './internal/color'
54
+ // Worklet-safe clamp shared by `useTouchDrag` and the gesture adapters'
55
+ // `useDrag`; exported so a custom drag can apply the same rubber-band rule.
56
+ export { applyBounds } from './touch/applyBounds'
51
57
  export {
52
58
  useAnimation,
53
59
  useAnimator,
@@ -61,6 +67,7 @@ export {
61
67
  useShadow,
62
68
  useSpring,
63
69
  useTransform,
70
+ useTranslateStyle,
64
71
  useVariants,
65
72
  } from './values'
66
73
  // The value-layer hooks above all return Reanimated `SharedValue`s — export
@@ -97,8 +104,10 @@ export type {
97
104
  EasingFunction,
98
105
  EasingFunctionFactory,
99
106
  EasingInput,
107
+ GestureLayerTransitions,
100
108
  GestureSubStates,
101
109
  MotionComponent,
110
+ MotionComponentProps,
102
111
  MotionProps,
103
112
  NamedTransitions,
104
113
  NoAnimationTransition,
@@ -1,4 +1,5 @@
1
1
  import { LinearTransition } from 'react-native-reanimated'
2
+ import { DEFAULT_LAYOUT_DURATION } from '../transitions/constants'
2
3
  import { ensureWorkletEasing } from '../transitions/easing'
3
4
  import { DEFAULT_SPRING, springToReanimated } from '../transitions/spring'
4
5
  import { type TransitionConfig } from '../types'
@@ -34,7 +35,9 @@ export function resolveLayoutTransition(
34
35
  if (cfg.type === 'no-animation') return undefined
35
36
 
36
37
  if (cfg.type === 'timing') {
37
- let builder = LinearTransition.duration(cfg.duration ?? 300)
38
+ let builder = LinearTransition.duration(
39
+ cfg.duration ?? DEFAULT_LAYOUT_DURATION,
40
+ )
38
41
  const easing = ensureWorkletEasing(cfg.easing)
39
42
  if (easing) builder = builder.easing(easing)
40
43
  if (cfg.delay) builder = builder.delay(cfg.delay)
@@ -15,6 +15,7 @@ import {
15
15
  withSpring,
16
16
  withTiming,
17
17
  } from 'react-native-reanimated'
18
+ import { DEFAULT_LAYOUT_DURATION } from '../transitions/constants'
18
19
  import { DEFAULT_SPRING, springToReanimated } from '../transitions/spring'
19
20
  import { type SpringTransition, type TransitionConfig } from '../types'
20
21
  import { measureWindowRect } from './measureWindow'
@@ -334,7 +335,7 @@ function legBuilder(
334
335
  transition: TransitionConfig | undefined,
335
336
  ): (from: number, to: number) => number {
336
337
  if (transition?.type === 'timing') {
337
- const duration = transition.duration ?? 300
338
+ const duration = transition.duration ?? DEFAULT_LAYOUT_DURATION
338
339
  return (from, to) =>
339
340
  withSequence(
340
341
  withTiming(from, { duration: 0 }),