@rootnative/inertia 0.0.0-alpha.4 → 0.0.0-alpha.6

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 (50) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/{chunk-5I3G43XA.js → chunk-2HYD2ZBK.js} +2 -2
  3. package/dist/chunk-3UTJJ4A3.js +8 -0
  4. package/dist/{chunk-Q6ZTMLTI.js → chunk-4PEHWDAZ.js} +7 -7
  5. package/dist/chunk-4QGXK6TF.js +8 -0
  6. package/dist/{chunk-WPPLZNM4.mjs → chunk-6SMPIOIC.mjs} +1 -1
  7. package/dist/{chunk-6EP3S2PN.js → chunk-7AOERN53.js} +3 -3
  8. package/dist/{chunk-6UQ4KA6V.js → chunk-7UDYEFBU.js} +22 -22
  9. package/dist/{chunk-K4KR5BIS.mjs → chunk-ALRHDFZE.mjs} +1 -1
  10. package/dist/{chunk-QQJSBIXV.mjs → chunk-CWLFUYIY.mjs} +1 -1
  11. package/dist/{chunk-6FENLMCA.mjs → chunk-CY7Y64C3.mjs} +17 -1
  12. package/dist/{chunk-I76OC6RX.mjs → chunk-DWCLIBYO.mjs} +2 -2
  13. package/dist/{chunk-IJNVUM5U.mjs → chunk-JVBXPF2G.mjs} +1 -1
  14. package/dist/{chunk-OBE7KTMK.mjs → chunk-NXDJZD6A.mjs} +1 -1
  15. package/dist/{chunk-SFRNO6AW.js → chunk-PTRF47DA.js} +17 -0
  16. package/dist/{chunk-L2EVRKSC.mjs → chunk-R63GIUNU.mjs} +1 -1
  17. package/dist/{chunk-ZQUCQRZT.mjs → chunk-RGNX6UZN.mjs} +2 -2
  18. package/dist/{chunk-OM5FXU4I.js → chunk-TDSO63CJ.js} +2 -2
  19. package/dist/chunk-Z7HIOFKQ.js +8 -0
  20. package/dist/gestureLayer/index.js +10 -10
  21. package/dist/gestureLayer/index.mjs +3 -3
  22. package/dist/index.d.mts +78 -13
  23. package/dist/index.d.ts +78 -13
  24. package/dist/index.js +202 -44
  25. package/dist/index.mjs +178 -20
  26. package/dist/motion/Image.js +5 -5
  27. package/dist/motion/Image.mjs +4 -4
  28. package/dist/motion/Pressable.js +5 -5
  29. package/dist/motion/Pressable.mjs +4 -4
  30. package/dist/motion/ScrollView.js +5 -5
  31. package/dist/motion/ScrollView.mjs +4 -4
  32. package/dist/motion/Text.js +5 -5
  33. package/dist/motion/Text.mjs +4 -4
  34. package/dist/motion/View.js +5 -5
  35. package/dist/motion/View.mjs +4 -4
  36. package/dist/touch/index.js +3 -3
  37. package/dist/touch/index.mjs +1 -1
  38. package/llms.txt +1 -1
  39. package/package.json +2 -2
  40. package/src/index.ts +1 -0
  41. package/src/internal/boxShadow.ts +204 -0
  42. package/src/internal/nonWorkletWarning.ts +41 -0
  43. package/src/layout/resolveLayout.ts +3 -2
  44. package/src/transitions/easing.ts +13 -8
  45. package/src/values/index.ts +1 -0
  46. package/src/values/useShadow.ts +76 -1
  47. package/src/values/useTransform.ts +28 -12
  48. package/dist/chunk-NDKVHL3N.js +0 -8
  49. package/dist/chunk-SCTX5Z7I.js +0 -8
  50. package/dist/chunk-WZGMAXKC.js +0 -8
package/CHANGELOG.md CHANGED
@@ -4,6 +4,28 @@ All notable changes to `@rootnative/inertia` are documented here. The format fol
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ### Added
8
+
9
+ - **`useShadow` now interpolates CSS `boxShadow`.** The classic `shadow*`/`elevation` keys never reach the web renderer, so a `useShadow` elevation crossfade silently dropped its shadow on web — the platform where hover, its most common driver, matters most (gap surfaced by the RootNative UI Card migration). `ShadowConfig` gains `boxShadow?: string | BoxShadowLayer[]`: pass the CSS string form design systems store elevation tokens in (px lengths only; parsed once on the JS thread, `cubicBezier`-style — malformed tokens throw at setup rather than warning) or structured layers mirroring RN's `BoxShadowValue`. Multi-layer shadows interpolate per layer with CSS-transition padding semantics (shorter side padded with invisible layers; a genuine `inset` mismatch throws); blur clamps at 0 under springy overshoot. Emitted as a `boxShadow` style string — passed through as CSS by react-native-web and rendered natively on RN 0.76+ new architecture; keep `shadow*`/`elevation` alongside it for old-arch native. New `BoxShadowLayer` type exported from the root.
10
+
11
+ ## [0.0.0-alpha.5] - 2026-07-21
12
+
13
+ ### Changed
14
+
15
+ - **Non-worklet transformers and easings now dev-warn.** `useTransform`'s transformer overload and custom `timing.easing` functions must be worklets (`'worklet'` directive as the first statement). The previous "plain functions are auto-wrapped" promise was unfulfillable: the directive-wrapped fallback closes over the opaque function reference, not the shared values read inside it, so Reanimated cannot extract dependencies (a `useTransform` derived value silently only refreshed on React re-renders — found via a frozen TextField label float in the UI library) and native builds reject the plain function when the closure is serialized to the UI thread. The fallback wrapper remains as a web-only best effort, but both sites now `console.warn` once in dev (suppressed under Jest, where the shared stubs report every function as non-worklet). Docs (`transitions.md`, `layout.md`, `api/hooks.md`) and docstrings corrected to state the real contract.
16
+
17
+ ## [0.0.0-alpha.4] - 2026-07-21
18
+
19
+ ### Fixed
20
+
21
+ - **First mouse click after page load no longer draws a focus ring** (web). The `focusVisibility` input-modality listeners attached lazily on the first `isFocusVisible()` call — which happens _during_ the focus dispatch of that first click, after its `mousedown` had already passed unobserved — leaving the default `'keyboard'` modality and misclassifying the pointer interaction as keyboard focus. The listeners now install eagerly at module import (the lazy path remains as a safety net for environments where `document` appears after import).
22
+
23
+ ## [0.0.0-alpha.3] - 2026-07-21
24
+
25
+ ### Fixed
26
+
27
+ - **Named transitions resolve correctly across subpath entries.** `splitting: false` in the tsup config made every dist entry inline its own copy of `MotionConfigContext`, so the provider (root entry) and consumers (e.g. the `/gesture-layer` subpath) held different React contexts and every registered name silently fell back to the default spring. Dist now builds with code splitting so the context module is shared.
28
+
7
29
  ## [0.0.0-alpha.2] - 2026-07-20
8
30
 
9
31
  ### Added
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
- var chunk6UQ4KA6V_js = require('./chunk-6UQ4KA6V.js');
3
+ var chunk7UDYEFBU_js = require('./chunk-7UDYEFBU.js');
4
4
  var reactNative = require('react-native');
5
5
 
6
- var MotionScrollView = chunk6UQ4KA6V_js.createMotionComponent(reactNative.ScrollView);
6
+ var MotionScrollView = chunk7UDYEFBU_js.createMotionComponent(reactNative.ScrollView);
7
7
 
8
8
  exports.MotionScrollView = MotionScrollView;
@@ -0,0 +1,8 @@
1
+ 'use strict';
2
+
3
+ var chunk7UDYEFBU_js = require('./chunk-7UDYEFBU.js');
4
+ var reactNative = require('react-native');
5
+
6
+ var MotionImage = chunk7UDYEFBU_js.createMotionComponent(reactNative.Image);
7
+
8
+ exports.MotionImage = MotionImage;
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunk6EP3S2PN_js = require('./chunk-6EP3S2PN.js');
4
- var chunkSFRNO6AW_js = require('./chunk-SFRNO6AW.js');
3
+ var chunk7AOERN53_js = require('./chunk-7AOERN53.js');
4
+ var chunkPTRF47DA_js = require('./chunk-PTRF47DA.js');
5
5
  var react = require('react');
6
6
  var reactNativeReanimated = require('react-native-reanimated');
7
7
 
@@ -10,12 +10,12 @@ function useGesture(transition) {
10
10
  const focused = reactNativeReanimated.useSharedValue(0);
11
11
  const focusVisible = reactNativeReanimated.useSharedValue(0);
12
12
  const hovered = reactNativeReanimated.useSharedValue(0);
13
- const shouldReduceMotion = chunk6EP3S2PN_js.useShouldReduceMotion();
14
- const resolved = chunk6EP3S2PN_js.resolveNamedTransitionProp(transition, chunk6EP3S2PN_js.useNamedTransitions());
13
+ const shouldReduceMotion = chunk7AOERN53_js.useShouldReduceMotion();
14
+ const resolved = chunk7AOERN53_js.resolveNamedTransitionProp(transition, chunk7AOERN53_js.useNamedTransitions());
15
15
  const setLayer = react.useCallback(
16
16
  (sv, layer, target) => {
17
17
  const cfg = shouldReduceMotion ? { type: "no-animation" } : layerTransition(layer, resolved) ?? { type: "spring" };
18
- sv.value = chunkSFRNO6AW_js.resolveTransition(cfg, target);
18
+ sv.value = chunkPTRF47DA_js.resolveTransition(cfg, target);
19
19
  },
20
20
  // The transition is intentionally read on every call rather than cooked
21
21
  // into the dep array — a fresh literal each render would otherwise
@@ -34,7 +34,7 @@ function useGesture(transition) {
34
34
  onHoverOut: () => setLayer(hovered, "hovered", 0),
35
35
  onFocus: () => {
36
36
  setLayer(focused, "focused", 1);
37
- if (chunk6EP3S2PN_js.isFocusVisible()) setLayer(focusVisible, "focusVisible", 1);
37
+ if (chunk7AOERN53_js.isFocusVisible()) setLayer(focusVisible, "focusVisible", 1);
38
38
  },
39
39
  onBlur: () => {
40
40
  setLayer(focused, "focused", 0);
@@ -47,7 +47,7 @@ function useGesture(transition) {
47
47
  }
48
48
  function layerTransition(layer, transition) {
49
49
  if (!transition) return void 0;
50
- if (chunkSFRNO6AW_js.isTopLevelTransition(transition)) return transition;
50
+ if (chunkPTRF47DA_js.isTopLevelTransition(transition)) return transition;
51
51
  return transition[layer];
52
52
  }
53
53
 
@@ -0,0 +1,8 @@
1
+ 'use strict';
2
+
3
+ var chunk7UDYEFBU_js = require('./chunk-7UDYEFBU.js');
4
+ var reactNative = require('react-native');
5
+
6
+ var MotionView = chunk7UDYEFBU_js.createMotionComponent(reactNative.View);
7
+
8
+ exports.MotionView = MotionView;
@@ -1,4 +1,4 @@
1
- import { createMotionComponent } from './chunk-I76OC6RX.mjs';
1
+ import { createMotionComponent } from './chunk-DWCLIBYO.mjs';
2
2
  import { View } from 'react-native';
3
3
 
4
4
  var MotionView = createMotionComponent(View);
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkSFRNO6AW_js = require('./chunk-SFRNO6AW.js');
3
+ var chunkPTRF47DA_js = require('./chunk-PTRF47DA.js');
4
4
  var react = require('react');
5
5
  var reactNativeReanimated = require('react-native-reanimated');
6
6
  var jsxRuntime = require('react/jsx-runtime');
@@ -32,7 +32,7 @@ function MotionConfig({
32
32
  children
33
33
  }) {
34
34
  const parent = useMotionConfig();
35
- const transitionsSig = chunkSFRNO6AW_js.stableSig(transitions);
35
+ const transitionsSig = chunkPTRF47DA_js.stableSig(transitions);
36
36
  const value = react.useMemo(
37
37
  () => ({
38
38
  reducedMotion: reducedMotion ?? parent.reducedMotion,
@@ -66,7 +66,7 @@ function resolveNamedTransitionProp(transition, registry) {
66
66
  if (typeof transition === "string") {
67
67
  return lookupNamedTransition(transition, registry);
68
68
  }
69
- if (chunkSFRNO6AW_js.isTopLevelTransition(transition)) return transition;
69
+ if (chunkPTRF47DA_js.isTopLevelTransition(transition)) return transition;
70
70
  const map = transition;
71
71
  let out = null;
72
72
  for (const key in map) {
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunk6EP3S2PN_js = require('./chunk-6EP3S2PN.js');
4
- var chunkSFRNO6AW_js = require('./chunk-SFRNO6AW.js');
3
+ var chunk7AOERN53_js = require('./chunk-7AOERN53.js');
4
+ var chunkPTRF47DA_js = require('./chunk-PTRF47DA.js');
5
5
  var react = require('react');
6
6
  var jsxRuntime = require('react/jsx-runtime');
7
7
  var Animated = require('react-native-reanimated');
@@ -111,14 +111,14 @@ function resolveLayoutTransition(layout) {
111
111
  if (cfg.type === "no-animation") return void 0;
112
112
  if (cfg.type === "timing") {
113
113
  let builder2 = Animated.LinearTransition.duration(cfg.duration ?? 300);
114
- const easing = chunkSFRNO6AW_js.ensureWorkletEasing(cfg.easing);
114
+ const easing = chunkPTRF47DA_js.ensureWorkletEasing(cfg.easing);
115
115
  if (easing) builder2 = builder2.easing(easing);
116
116
  if (cfg.delay) builder2 = builder2.delay(cfg.delay);
117
117
  return builder2;
118
118
  }
119
119
  const spring = cfg.type === "decay" ? { type: "spring" } : cfg;
120
- const { stiffness, damping, mass } = chunkSFRNO6AW_js.springToReanimated({
121
- ...chunkSFRNO6AW_js.DEFAULT_SPRING,
120
+ const { stiffness, damping, mass } = chunkPTRF47DA_js.springToReanimated({
121
+ ...chunkPTRF47DA_js.DEFAULT_SPRING,
122
122
  ...spring
123
123
  });
124
124
  let builder = Animated.LinearTransition.springify().stiffness(stiffness).damping(damping).mass(mass);
@@ -257,8 +257,8 @@ function applyFlip(args) {
257
257
  );
258
258
  return;
259
259
  }
260
- const springCfg = transition?.type === "spring" ? { ...chunkSFRNO6AW_js.DEFAULT_SPRING, ...transition } : { type: "spring", ...chunkSFRNO6AW_js.DEFAULT_SPRING };
261
- const springParams = chunkSFRNO6AW_js.springToReanimated(springCfg);
260
+ const springCfg = transition?.type === "spring" ? { ...chunkPTRF47DA_js.DEFAULT_SPRING, ...transition } : { type: "spring", ...chunkPTRF47DA_js.DEFAULT_SPRING };
261
+ const springParams = chunkPTRF47DA_js.springToReanimated(springCfg);
262
262
  dx.value = Animated.withSequence(
263
263
  Animated.withTiming(deltaX, { duration: 0 }),
264
264
  Animated.withSpring(0, springParams)
@@ -379,14 +379,14 @@ var DEFAULT_RESTING = {
379
379
  function transitionFor(prop, transition) {
380
380
  if (!transition) return void 0;
381
381
  if (typeof transition === "string") return void 0;
382
- if (chunkSFRNO6AW_js.isTopLevelTransition(transition)) return transition;
382
+ if (chunkPTRF47DA_js.isTopLevelTransition(transition)) return transition;
383
383
  if (GESTURE_LAYER_NAME_SET.has(prop)) return void 0;
384
384
  return transition[prop];
385
385
  }
386
386
  function gestureLayerTransitionFor(layer, transition) {
387
387
  if (!transition) return void 0;
388
388
  if (typeof transition === "string") return void 0;
389
- if (chunkSFRNO6AW_js.isTopLevelTransition(transition)) return transition;
389
+ if (chunkPTRF47DA_js.isTopLevelTransition(transition)) return transition;
390
390
  return transition[layer];
391
391
  }
392
392
  function createMotionComponent(Component) {
@@ -411,12 +411,12 @@ function createMotionComponent(Component) {
411
411
  onLayout: userOnLayout,
412
412
  ...rest
413
413
  } = props;
414
- const namedTransitions = chunk6EP3S2PN_js.useNamedTransitions();
415
- const transition = chunk6EP3S2PN_js.resolveNamedTransitionProp(
414
+ const namedTransitions = chunk7AOERN53_js.useNamedTransitions();
415
+ const transition = chunk7AOERN53_js.resolveNamedTransitionProp(
416
416
  transitionProp,
417
417
  namedTransitions
418
418
  );
419
- const layout = typeof layoutProp === "string" ? chunk6EP3S2PN_js.lookupNamedTransition(layoutProp, namedTransitions) : layoutProp;
419
+ const layout = typeof layoutProp === "string" ? chunk7AOERN53_js.lookupNamedTransition(layoutProp, namedTransitions) : layoutProp;
420
420
  if (__DEV__ && typeof style === "function") {
421
421
  throw new Error(
422
422
  "[inertia] `style` must be a style object or array of style objects, not a function. The function-form `style={(state) => ...}` Pressable API is not supported \u2014 use `gesture.pressed` (or `gesture.focused`, etc.) to drive state-dependent styling instead."
@@ -424,7 +424,7 @@ function createMotionComponent(Component) {
424
424
  }
425
425
  const presence = usePresence();
426
426
  const isExiting = presence !== null && presence.isPresent === false;
427
- const shouldReduceMotion = chunk6EP3S2PN_js.useShouldReduceMotion();
427
+ const shouldReduceMotion = chunk7AOERN53_js.useShouldReduceMotion();
428
428
  const onAnimationEndRef = react.useRef(onAnimationEnd);
429
429
  onAnimationEndRef.current = onAnimationEnd;
430
430
  const variantKey = useControllerKey(controller);
@@ -509,13 +509,13 @@ function createMotionComponent(Component) {
509
509
  const gestureSV = Animated.useSharedValue(
510
510
  resolveGestureLayers(gesture)
511
511
  );
512
- const gestureTargetsSig = chunkSFRNO6AW_js.stableSig(gesture);
512
+ const gestureTargetsSig = chunkPTRF47DA_js.stableSig(gesture);
513
513
  react.useEffect(() => {
514
514
  gestureSV.value = resolveGestureLayers(gesture);
515
515
  }, [gestureTargetsSig]);
516
516
  const baseRecord = isExiting && exitRecord ? { ...animateRecord, ...exitRecord } : animateRecord;
517
- const baseSig = chunkSFRNO6AW_js.stableSig(baseRecord) + (isExiting ? "|exit" : "") + (shouldReduceMotion ? "|rm" : "");
518
- const transitionSig = chunkSFRNO6AW_js.stableSig(transition);
517
+ const baseSig = chunkPTRF47DA_js.stableSig(baseRecord) + (isExiting ? "|exit" : "") + (shouldReduceMotion ? "|rm" : "");
518
+ const transitionSig = chunkPTRF47DA_js.stableSig(transition);
519
519
  const safeToRemoveRef = react.useRef(void 0);
520
520
  safeToRemoveRef.current = presence?.safeToRemove;
521
521
  react.useEffect(() => {
@@ -563,7 +563,7 @@ function createMotionComponent(Component) {
563
563
  isExiting ? onSettle : void 0,
564
564
  TRANSFORM_KEY_SET.has(key) ? transformGroup : void 0
565
565
  );
566
- sharedValues[key].value = chunkSFRNO6AW_js.resolveAnimatableValue(
566
+ sharedValues[key].value = chunkPTRF47DA_js.resolveAnimatableValue(
567
567
  target,
568
568
  cfg,
569
569
  factory
@@ -612,7 +612,7 @@ function createMotionComponent(Component) {
612
612
  const sharedLayout = useSharedLayout({
613
613
  layoutId,
614
614
  userRef: ref,
615
- transition: chunkSFRNO6AW_js.isTopLevelTransition(transition) ? transition : void 0,
615
+ transition: chunkPTRF47DA_js.isTopLevelTransition(transition) ? transition : void 0,
616
616
  shouldReduceMotion,
617
617
  userOnLayout
618
618
  });
@@ -690,7 +690,7 @@ function createMotionComponent(Component) {
690
690
  setFocusVisible,
691
691
  setHovered
692
692
  );
693
- const layoutSig = chunkSFRNO6AW_js.stableSig(layout);
693
+ const layoutSig = chunkPTRF47DA_js.stableSig(layout);
694
694
  const layoutTransition = react.useMemo(
695
695
  () => shouldReduceMotion ? void 0 : resolveLayoutTransition(layout),
696
696
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -934,7 +934,7 @@ function resolveGestureLayers(gesture) {
934
934
  return out;
935
935
  }
936
936
  function useGestureLayerProgress(progress, active, declared, layer, transition, isExiting, shouldReduceMotion) {
937
- const layerCfgSig = chunkSFRNO6AW_js.stableSig(gestureLayerTransitionFor(layer, transition));
937
+ const layerCfgSig = chunkPTRF47DA_js.stableSig(gestureLayerTransitionFor(layer, transition));
938
938
  react.useEffect(() => {
939
939
  if (!declared) return;
940
940
  if (isExiting) {
@@ -943,7 +943,7 @@ function useGestureLayerProgress(progress, active, declared, layer, transition,
943
943
  }
944
944
  const target = active ? 1 : 0;
945
945
  const cfg = shouldReduceMotion ? { type: "no-animation" } : gestureLayerTransitionFor(layer, transition) ?? { type: "spring" };
946
- progress.value = chunkSFRNO6AW_js.resolveTransition(cfg, target);
946
+ progress.value = chunkPTRF47DA_js.resolveTransition(cfg, target);
947
947
  }, [active, declared, isExiting, shouldReduceMotion, layerCfgSig]);
948
948
  }
949
949
  function useGestureHandlers(gesture, rest, setPressed, setFocused, setFocusVisible, setHovered) {
@@ -967,7 +967,7 @@ function useGestureHandlers(gesture, rest, setPressed, setFocused, setFocusVisib
967
967
  if (gesture.focused || gesture.focusVisible) {
968
968
  handlers.onFocus = compose(rest.onFocus, () => {
969
969
  if (gesture.focused) setFocused(true);
970
- if (gesture.focusVisible && chunk6EP3S2PN_js.isFocusVisible()) setFocusVisible(true);
970
+ if (gesture.focusVisible && chunk7AOERN53_js.isFocusVisible()) setFocusVisible(true);
971
971
  });
972
972
  handlers.onBlur = compose(rest.onBlur, () => {
973
973
  if (gesture.focused) setFocused(false);
@@ -1,4 +1,4 @@
1
- import { createMotionComponent } from './chunk-I76OC6RX.mjs';
1
+ import { createMotionComponent } from './chunk-DWCLIBYO.mjs';
2
2
  import { Image } from 'react-native';
3
3
 
4
4
  var MotionImage = createMotionComponent(Image);
@@ -1,4 +1,4 @@
1
- import { createMotionComponent } from './chunk-I76OC6RX.mjs';
1
+ import { createMotionComponent } from './chunk-DWCLIBYO.mjs';
2
2
  import { ScrollView } from 'react-native';
3
3
 
4
4
  var MotionScrollView = createMotionComponent(ScrollView);
@@ -1,11 +1,27 @@
1
1
  import { isWorkletFunction } from 'react-native-worklets';
2
2
  import { withSequence, Easing, withDecay, withTiming, withSpring, withRepeat, withDelay } from 'react-native-reanimated';
3
3
 
4
+ // src/transitions/easing.ts
5
+
6
+ // src/internal/nonWorkletWarning.ts
7
+ var warned = /* @__PURE__ */ new Set();
8
+ function warnNonWorkletOnce(key, message) {
9
+ if (!__DEV__) return;
10
+ if (typeof process !== "undefined" && process.env?.JEST_WORKER_ID) return;
11
+ if (warned.has(key)) return;
12
+ warned.add(key);
13
+ console.warn(message);
14
+ }
15
+
4
16
  // src/transitions/easing.ts
5
17
  function ensureWorkletEasing(easing) {
6
18
  if (!easing) return void 0;
7
19
  const fn = isEasingFactory(easing) ? easing.factory() : easing;
8
20
  if (isWorkletFunction(fn)) return fn;
21
+ warnNonWorkletOnce(
22
+ "timing-easing",
23
+ "[inertia] timing easing: the provided easing function is not a worklet. The fallback wrapper works on web but native builds reject it when the transition runs on the UI thread. Add the 'worklet' directive as the first statement of the easing function, or use Reanimated's Easing.* helpers / inertia's cubicBezier(), which are already worklets."
24
+ );
9
25
  const wrapped = (t) => {
10
26
  "worklet";
11
27
  return fn(t);
@@ -254,4 +270,4 @@ function stableStringify(v) {
254
270
  return "{" + keys.map((k) => JSON.stringify(k) + ":" + stableStringify(obj[k])).join(",") + "}";
255
271
  }
256
272
 
257
- export { DEFAULT_SPRING, buildReleaseAnimation, cubicBezier, ensureWorkletEasing, isTopLevelTransition, resolveAnimatableValue, resolveTransition, springToReanimated, stableSig };
273
+ export { DEFAULT_SPRING, buildReleaseAnimation, cubicBezier, ensureWorkletEasing, isTopLevelTransition, resolveAnimatableValue, resolveTransition, springToReanimated, stableSig, warnNonWorkletOnce };
@@ -1,5 +1,5 @@
1
- import { useNamedTransitions, resolveNamedTransitionProp, lookupNamedTransition, useShouldReduceMotion, isFocusVisible } from './chunk-L2EVRKSC.mjs';
2
- import { stableSig, resolveAnimatableValue, isTopLevelTransition, resolveTransition, ensureWorkletEasing, springToReanimated, DEFAULT_SPRING } from './chunk-6FENLMCA.mjs';
1
+ import { useNamedTransitions, resolveNamedTransitionProp, lookupNamedTransition, useShouldReduceMotion, isFocusVisible } from './chunk-R63GIUNU.mjs';
2
+ import { stableSig, resolveAnimatableValue, isTopLevelTransition, resolveTransition, ensureWorkletEasing, springToReanimated, DEFAULT_SPRING } from './chunk-CY7Y64C3.mjs';
3
3
  import { createContext, useContext, useMemo, Children, isValidElement, useState, useRef, useCallback, forwardRef, useEffect } from 'react';
4
4
  import { jsx, Fragment } from 'react/jsx-runtime';
5
5
  import Animated, { useSharedValue, useAnimatedStyle, interpolateColor, reanimatedVersion, runOnJS, LinearTransition, withSequence, withTiming, withSpring } from 'react-native-reanimated';
@@ -1,4 +1,4 @@
1
- import { createMotionComponent } from './chunk-I76OC6RX.mjs';
1
+ import { createMotionComponent } from './chunk-DWCLIBYO.mjs';
2
2
  import { Text } from 'react-native';
3
3
 
4
4
  var MotionText = createMotionComponent(Text);
@@ -1,4 +1,4 @@
1
- import { createMotionComponent } from './chunk-I76OC6RX.mjs';
1
+ import { createMotionComponent } from './chunk-DWCLIBYO.mjs';
2
2
  import { Pressable } from 'react-native';
3
3
 
4
4
  var MotionPressable = createMotionComponent(Pressable);
@@ -3,11 +3,27 @@
3
3
  var reactNativeWorklets = require('react-native-worklets');
4
4
  var reactNativeReanimated = require('react-native-reanimated');
5
5
 
6
+ // src/transitions/easing.ts
7
+
8
+ // src/internal/nonWorkletWarning.ts
9
+ var warned = /* @__PURE__ */ new Set();
10
+ function warnNonWorkletOnce(key, message) {
11
+ if (!__DEV__) return;
12
+ if (typeof process !== "undefined" && process.env?.JEST_WORKER_ID) return;
13
+ if (warned.has(key)) return;
14
+ warned.add(key);
15
+ console.warn(message);
16
+ }
17
+
6
18
  // src/transitions/easing.ts
7
19
  function ensureWorkletEasing(easing) {
8
20
  if (!easing) return void 0;
9
21
  const fn = isEasingFactory(easing) ? easing.factory() : easing;
10
22
  if (reactNativeWorklets.isWorkletFunction(fn)) return fn;
23
+ warnNonWorkletOnce(
24
+ "timing-easing",
25
+ "[inertia] timing easing: the provided easing function is not a worklet. The fallback wrapper works on web but native builds reject it when the transition runs on the UI thread. Add the 'worklet' directive as the first statement of the easing function, or use Reanimated's Easing.* helpers / inertia's cubicBezier(), which are already worklets."
26
+ );
11
27
  const wrapped = (t) => {
12
28
  "worklet";
13
29
  return fn(t);
@@ -265,3 +281,4 @@ exports.resolveAnimatableValue = resolveAnimatableValue;
265
281
  exports.resolveTransition = resolveTransition;
266
282
  exports.springToReanimated = springToReanimated;
267
283
  exports.stableSig = stableSig;
284
+ exports.warnNonWorkletOnce = warnNonWorkletOnce;
@@ -1,4 +1,4 @@
1
- import { stableSig, isTopLevelTransition } from './chunk-6FENLMCA.mjs';
1
+ import { stableSig, isTopLevelTransition } from './chunk-CY7Y64C3.mjs';
2
2
  import { createContext, useContext, useMemo } from 'react';
3
3
  import { useReducedMotion } from 'react-native-reanimated';
4
4
  import { jsx } from 'react/jsx-runtime';
@@ -1,5 +1,5 @@
1
- import { useShouldReduceMotion, resolveNamedTransitionProp, useNamedTransitions, isFocusVisible } from './chunk-L2EVRKSC.mjs';
2
- import { resolveTransition, isTopLevelTransition } from './chunk-6FENLMCA.mjs';
1
+ import { useShouldReduceMotion, resolveNamedTransitionProp, useNamedTransitions, isFocusVisible } from './chunk-R63GIUNU.mjs';
2
+ import { resolveTransition, isTopLevelTransition } from './chunk-CY7Y64C3.mjs';
3
3
  import { useCallback, useMemo } from 'react';
4
4
  import { useSharedValue } from 'react-native-reanimated';
5
5
 
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
- var chunk6UQ4KA6V_js = require('./chunk-6UQ4KA6V.js');
3
+ var chunk7UDYEFBU_js = require('./chunk-7UDYEFBU.js');
4
4
  var reactNative = require('react-native');
5
5
 
6
- var MotionPressable = chunk6UQ4KA6V_js.createMotionComponent(reactNative.Pressable);
6
+ var MotionPressable = chunk7UDYEFBU_js.createMotionComponent(reactNative.Pressable);
7
7
 
8
8
  exports.MotionPressable = MotionPressable;
@@ -0,0 +1,8 @@
1
+ 'use strict';
2
+
3
+ var chunk7UDYEFBU_js = require('./chunk-7UDYEFBU.js');
4
+ var reactNative = require('react-native');
5
+
6
+ var MotionText = chunk7UDYEFBU_js.createMotionComponent(reactNative.Text);
7
+
8
+ exports.MotionText = MotionText;
@@ -1,25 +1,25 @@
1
1
  'use strict';
2
2
 
3
- var chunkQ6ZTMLTI_js = require('../chunk-Q6ZTMLTI.js');
4
- var chunk6EP3S2PN_js = require('../chunk-6EP3S2PN.js');
5
- var chunkSFRNO6AW_js = require('../chunk-SFRNO6AW.js');
3
+ var chunk4PEHWDAZ_js = require('../chunk-4PEHWDAZ.js');
4
+ var chunk7AOERN53_js = require('../chunk-7AOERN53.js');
5
+ var chunkPTRF47DA_js = require('../chunk-PTRF47DA.js');
6
6
  var react = require('react');
7
7
  var reactNativeReanimated = require('react-native-reanimated');
8
8
 
9
9
  function useGestureLayer(states, options = {}) {
10
10
  const { disabled: isDisabled = false, transition: transitionInput } = options;
11
- const shouldReduceMotion = chunk6EP3S2PN_js.useShouldReduceMotion();
12
- const transition = chunk6EP3S2PN_js.resolveNamedTransitionProp(
11
+ const shouldReduceMotion = chunk7AOERN53_js.useShouldReduceMotion();
12
+ const transition = chunk7AOERN53_js.resolveNamedTransitionProp(
13
13
  transitionInput,
14
- chunk6EP3S2PN_js.useNamedTransitions()
14
+ chunk7AOERN53_js.useNamedTransitions()
15
15
  );
16
- const gesture = chunkQ6ZTMLTI_js.useGesture(transition);
16
+ const gesture = chunk4PEHWDAZ_js.useGesture(transition);
17
17
  const disabledProgress = reactNativeReanimated.useSharedValue(0);
18
- const transitionSig = chunkSFRNO6AW_js.stableSig(transition);
18
+ const transitionSig = chunkPTRF47DA_js.stableSig(transition);
19
19
  react.useEffect(() => {
20
20
  const target = isDisabled ? 1 : 0;
21
21
  const cfg = shouldReduceMotion ? { type: "no-animation" } : disabledTransition(transition) ?? { type: "spring" };
22
- disabledProgress.value = chunkSFRNO6AW_js.resolveTransition(cfg, target);
22
+ disabledProgress.value = chunkPTRF47DA_js.resolveTransition(cfg, target);
23
23
  }, [isDisabled, shouldReduceMotion, transitionSig, disabledProgress]);
24
24
  const meta = react.useMemo(() => {
25
25
  const layers = {
@@ -154,7 +154,7 @@ function useGestureLayer(states, options = {}) {
154
154
  }
155
155
  function disabledTransition(transition) {
156
156
  if (!transition) return void 0;
157
- if (chunkSFRNO6AW_js.isTopLevelTransition(transition)) return transition;
157
+ if (chunkPTRF47DA_js.isTopLevelTransition(transition)) return transition;
158
158
  return void 0;
159
159
  }
160
160
 
@@ -1,6 +1,6 @@
1
- import { useGesture } from '../chunk-ZQUCQRZT.mjs';
2
- import { useShouldReduceMotion, resolveNamedTransitionProp, useNamedTransitions } from '../chunk-L2EVRKSC.mjs';
3
- import { stableSig, resolveTransition, isTopLevelTransition } from '../chunk-6FENLMCA.mjs';
1
+ import { useGesture } from '../chunk-RGNX6UZN.mjs';
2
+ import { useShouldReduceMotion, resolveNamedTransitionProp, useNamedTransitions } from '../chunk-R63GIUNU.mjs';
3
+ import { stableSig, resolveTransition, isTopLevelTransition } from '../chunk-CY7Y64C3.mjs';
4
4
  import { useEffect, useMemo } from 'react';
5
5
  import { useSharedValue, useAnimatedStyle, interpolateColor } from 'react-native-reanimated';
6
6
 
package/dist/index.d.mts CHANGED
@@ -250,15 +250,15 @@ declare function cubicBezier(css: string): EasingInput;
250
250
  /**
251
251
  * Reanimated 3.9+ validates that easing functions used in nested-transition
252
252
  * contexts (variants, sequences, per-property maps) are worklets, and crashes
253
- * with `[Reanimated] The easing function is not a worklet` otherwise. The
254
- * library accepts plain functions on the public surface; this helper wraps
255
- * them so consumers don't have to think about the worklet boundary.
253
+ * with `[Reanimated] The easing function is not a worklet` otherwise.
256
254
  *
257
- * If the input is already a worklet (has been processed by the worklets babel
258
- * plugin), it's returned as-is. Otherwise it's wrapped in a function whose
259
- * body declares the `'worklet'` directive when our source is processed by
260
- * the consumer's worklets babel plugin (the default Expo/RN setup), the
261
- * wrapper becomes a real worklet that captures the user fn via closure.
255
+ * Custom easing functions MUST therefore be worklets put the `'worklet'`
256
+ * directive as the function's first statement (Reanimated's built-in
257
+ * `Easing.*` helpers and inertia's `cubicBezier()` already are). A plain
258
+ * function warns in dev and falls back to a directive-wrapped call-through;
259
+ * that wrapper works on web (single-threaded) but its closure holds the
260
+ * opaque plain function, which native builds reject when the transition's
261
+ * config is serialized to the UI thread.
262
262
  *
263
263
  * Reanimated 4 changed `Easing.bezier(...)` to return an
264
264
  * `EasingFunctionFactory` (`{ factory: () => EasingFunction }`) rather than
@@ -479,9 +479,17 @@ interface UseTransformOptions {
479
479
  * const distance = useTransform(() => Math.sqrt(x.value ** 2 + y.value ** 2))
480
480
  * ```
481
481
  *
482
- * The transformer must be a worklet (or a plain function we auto-wrap
483
- * see the easing wrapper for the rationale). It runs on the UI thread on
484
- * every frame where any read shared value changes.
482
+ * The transformer MUST be a worklet put the `'worklet'` directive as its
483
+ * first statement so the consumer's Babel plugin captures the shared values
484
+ * it reads as its closure. It runs on the UI thread on every frame where
485
+ * any read shared value changes.
486
+ *
487
+ * A plain function cannot work here, and the hook warns in dev when it gets
488
+ * one: the best-effort wrapper it falls back to closes over the opaque
489
+ * function reference, not the shared values read inside it, so Reanimated
490
+ * can't track them as dependencies — the derived value only refreshes on
491
+ * React re-renders, and native builds reject the plain function when the
492
+ * closure crosses to the UI thread.
485
493
  */
486
494
  declare function useTransform<T>(transformer: () => T): SharedValue<T>;
487
495
  /**
@@ -547,11 +555,42 @@ interface UseScrollResult {
547
555
  */
548
556
  declare function useScroll(): UseScrollResult;
549
557
 
558
+ /**
559
+ * CSS `box-shadow` parsing + pairing for `useShadow`.
560
+ *
561
+ * Design systems store web elevation tokens as CSS `box-shadow` strings
562
+ * (`'0px 1px 2px rgba(0,0,0,0.3), 0px 1px 3px 1px rgba(0,0,0,0.15)'`).
563
+ * Like `cubicBezier`, this module makes those tokens directly consumable:
564
+ * strings are parsed once on the JS thread into flat layer records the
565
+ * `useShadow` worklet can interpolate without any frame-time string work.
566
+ *
567
+ * Invalid input **throws** rather than warning — shadow tokens are
568
+ * constructed at theme/module setup, and a malformed token should fail
569
+ * loudly there, not silently render the wrong elevation.
570
+ */
571
+ /**
572
+ * One layer of a `box-shadow`, structurally mirroring React Native's
573
+ * `BoxShadowValue` (RN 0.76+ `boxShadow` style). Lengths are px numbers.
574
+ */
575
+ interface BoxShadowLayer {
576
+ offsetX: number;
577
+ offsetY: number;
578
+ /** Must be >= 0, per CSS. @default 0 */
579
+ blurRadius?: number;
580
+ /** @default 0 */
581
+ spreadDistance?: number;
582
+ /** Any color string Reanimated's `interpolateColor` accepts. @default 'black' */
583
+ color?: string;
584
+ /** @default false */
585
+ inset?: boolean;
586
+ }
587
+
550
588
  /**
551
589
  * Shape accepted on either end of a `useShadow` tween. Every field is
552
590
  * optional — only keys present on at least one side participate in the
553
591
  * output style. Mirrors the flat shadow keys on `Motion.View`'s `animate`
554
- * surface, plus the nested `shadowOffset` source.
592
+ * surface, plus the nested `shadowOffset` source and the CSS `boxShadow`
593
+ * surface.
555
594
  */
556
595
  interface ShadowConfig {
557
596
  shadowOpacity?: number;
@@ -563,6 +602,19 @@ interface ShadowConfig {
563
602
  /** Android elevation. iOS shadow consumers can leave this off. */
564
603
  elevation?: number;
565
604
  shadowColor?: string;
605
+ /**
606
+ * CSS `box-shadow` — the shadow surface on web (react-native-web passes
607
+ * it through as CSS) and on React Native 0.76+ new-architecture native.
608
+ * Accepts the CSS string form design systems store elevation tokens in
609
+ * (`'0px 1px 2px rgba(0,0,0,0.3), 0px 1px 3px 1px rgba(0,0,0,0.15)'`;
610
+ * px lengths only) or structured layers. Multi-layer shadows interpolate
611
+ * per layer; when one side has fewer layers, it is padded with invisible
612
+ * layers, CSS-transition style. A malformed string **throws** at render
613
+ * (like `cubicBezier` — token mistakes should fail loudly at setup).
614
+ * The classic `shadow*`/`elevation` keys don't reach the web renderer —
615
+ * provide `boxShadow` alongside them when the tween must show up there.
616
+ */
617
+ boxShadow?: string | readonly BoxShadowLayer[];
566
618
  }
567
619
  interface UseShadowOptions {
568
620
  /** Shadow state at `progress === 0`. */
@@ -599,6 +651,19 @@ interface UseShadowOptions {
599
651
  * `shadowColor`, `{ width: 0, height: 0 }` for `shadowOffset`). This is a
600
652
  * pure interpolator — to "animate" the shadow, drive `progress` with a
601
653
  * spring, timing, or gesture upstream.
654
+ *
655
+ * The classic `shadow*`/`elevation` keys don't render on web. When the
656
+ * tween must show up there (or on RN 0.76+ new-arch native via the CSS
657
+ * shadow model), provide `boxShadow` on both ends — CSS string tokens or
658
+ * structured layers; multi-layer shadows interpolate per layer:
659
+ *
660
+ * ```tsx
661
+ * const shadowStyle = useShadow({
662
+ * from: { boxShadow: theme.elevation.level1 }, // '0px 1px 2px rgba(0,0,0,0.3), 0px 1px 3px 1px rgba(0,0,0,0.15)'
663
+ * to: { boxShadow: theme.elevation.level2 },
664
+ * progress,
665
+ * })
666
+ * ```
602
667
  */
603
668
  declare function useShadow({ from, to, progress, }: UseShadowOptions): ReturnType<typeof useAnimatedStyle>;
604
669
 
@@ -615,4 +680,4 @@ declare function useShadow({ from, to, progress, }: UseShadowOptions): ReturnTyp
615
680
  */
616
681
  declare function useVariants<V extends Readonly<Record<string, object>>>(variants: V, initial?: keyof V & string): VariantController<keyof V & string>;
617
682
 
618
- export { AnimatableValue, 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 };
683
+ 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 };