@rootnative/inertia 0.0.2 → 0.0.4

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 (77) hide show
  1. package/CHANGELOG.md +63 -5
  2. package/README.md +5 -3
  3. package/dist/{chunk-ZN3PNGHQ.mjs → chunk-4ASOELLA.mjs} +1 -1
  4. package/dist/{chunk-LYMLQ6WQ.mjs → chunk-55W7BNO2.mjs} +604 -106
  5. package/dist/chunk-5SRD2WCO.js +8 -0
  6. package/dist/{chunk-PTRF47DA.js → chunk-7A6WTXNK.js} +10 -3
  7. package/dist/{chunk-NKA6XR77.js → chunk-CENTULW6.js} +2 -2
  8. package/dist/{chunk-4PEHWDAZ.js → chunk-D5KAHWMC.js} +7 -7
  9. package/dist/{chunk-2DHKV2XY.mjs → chunk-J5Q46OPW.mjs} +1 -1
  10. package/dist/{chunk-RGNX6UZN.mjs → chunk-K3CLP74S.mjs} +2 -2
  11. package/dist/{chunk-IWLU3VDE.js → chunk-MYE5NMXW.js} +623 -123
  12. package/dist/{chunk-HFDZAHWP.mjs → chunk-NAOXQJ7U.mjs} +1 -1
  13. package/dist/{chunk-R63GIUNU.mjs → chunk-QKC3APP4.mjs} +1 -1
  14. package/dist/{chunk-V6BTXHZK.mjs → chunk-RF7J5FRM.mjs} +1 -1
  15. package/dist/{chunk-CY7Y64C3.mjs → chunk-TU2XFPAK.mjs} +10 -4
  16. package/dist/chunk-TVFNJ25Z.js +8 -0
  17. package/dist/chunk-VLDIFL3F.js +8 -0
  18. package/dist/{chunk-7AOERN53.js → chunk-WVRCKOPO.js} +3 -3
  19. package/dist/{chunk-TUYHTHVV.js → chunk-XMEVPEMH.js} +2 -2
  20. package/dist/{chunk-TUMNV4P7.mjs → chunk-YKGY22SB.mjs} +1 -1
  21. package/dist/gestureLayer/index.d.mts +2 -2
  22. package/dist/gestureLayer/index.d.ts +2 -2
  23. package/dist/gestureLayer/index.js +10 -10
  24. package/dist/gestureLayer/index.mjs +3 -3
  25. package/dist/index.d.mts +14 -12
  26. package/dist/index.d.ts +14 -12
  27. package/dist/index.js +68 -176
  28. package/dist/index.mjs +40 -147
  29. package/dist/motion/Image.d.mts +1 -1
  30. package/dist/motion/Image.d.ts +1 -1
  31. package/dist/motion/Image.js +5 -5
  32. package/dist/motion/Image.mjs +4 -4
  33. package/dist/motion/Pressable.d.mts +1 -1
  34. package/dist/motion/Pressable.d.ts +1 -1
  35. package/dist/motion/Pressable.js +5 -5
  36. package/dist/motion/Pressable.mjs +4 -4
  37. package/dist/motion/ScrollView.d.mts +1 -1
  38. package/dist/motion/ScrollView.d.ts +1 -1
  39. package/dist/motion/ScrollView.js +5 -5
  40. package/dist/motion/ScrollView.mjs +4 -4
  41. package/dist/motion/Text.d.mts +1 -1
  42. package/dist/motion/Text.d.ts +1 -1
  43. package/dist/motion/Text.js +5 -5
  44. package/dist/motion/Text.mjs +4 -4
  45. package/dist/motion/View.d.mts +1 -1
  46. package/dist/motion/View.d.ts +1 -1
  47. package/dist/motion/View.js +5 -5
  48. package/dist/motion/View.mjs +4 -4
  49. package/dist/touch/index.d.mts +1 -1
  50. package/dist/touch/index.d.ts +1 -1
  51. package/dist/touch/index.js +3 -3
  52. package/dist/touch/index.mjs +1 -1
  53. package/dist/{types-G1dBU2IQ.d.mts → types-37pN82yh.d.mts} +49 -14
  54. package/dist/{types-G1dBU2IQ.d.ts → types-37pN82yh.d.ts} +49 -14
  55. package/dist/{useGesture-D1e4ixJo.d.ts → useGesture-Cl4uzZIr.d.ts} +1 -1
  56. package/dist/{useGesture-RFY6kTL3.d.mts → useGesture-_IKkS8Dv.d.mts} +1 -1
  57. package/llms.txt +3 -1
  58. package/package.json +1 -1
  59. package/src/index.ts +2 -1
  60. package/src/internal/boxShadow.ts +177 -6
  61. package/src/internal/nonWorkletWarning.ts +4 -6
  62. package/src/internal/warnOnce.ts +28 -0
  63. package/src/layout/index.ts +11 -0
  64. package/src/layout/measureWindow.ts +135 -0
  65. package/src/layout/sharedRegistry.ts +156 -18
  66. package/src/layout/useSharedLayout.ts +256 -91
  67. package/src/motion/createMotionComponent.tsx +550 -55
  68. package/src/motion/installCheck.ts +1 -1
  69. package/src/presence/Presence.tsx +73 -10
  70. package/src/transitions/index.ts +1 -1
  71. package/src/types.ts +52 -12
  72. package/src/values/useAnimator.ts +25 -14
  73. package/src/values/useColorCascade.ts +34 -16
  74. package/src/values/useColorTransition.ts +1 -1
  75. package/dist/chunk-34Q4UM6V.js +0 -8
  76. package/dist/chunk-KYJROYCG.js +0 -8
  77. package/dist/chunk-X5J5M3K3.js +0 -8
@@ -1,10 +1,11 @@
1
1
  'use strict';
2
2
 
3
- var chunk7AOERN53_js = require('./chunk-7AOERN53.js');
4
- var chunkPTRF47DA_js = require('./chunk-PTRF47DA.js');
3
+ var chunkWVRCKOPO_js = require('./chunk-WVRCKOPO.js');
4
+ var chunk7A6WTXNK_js = require('./chunk-7A6WTXNK.js');
5
5
  var react = require('react');
6
6
  var jsxRuntime = require('react/jsx-runtime');
7
7
  var Animated = require('react-native-reanimated');
8
+ var reactNative = require('react-native');
8
9
 
9
10
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
10
11
 
@@ -35,6 +36,8 @@ function Presence({ children }) {
35
36
  () => /* @__PURE__ */ new Map()
36
37
  );
37
38
  const prevIncomingRef = react.useRef(incoming);
39
+ const orderRef = react.useRef([]);
40
+ let pendingExiting = null;
38
41
  if (prevIncomingRef.current !== incoming) {
39
42
  const prev = prevIncomingRef.current;
40
43
  prevIncomingRef.current = incoming;
@@ -56,8 +59,12 @@ function Presence({ children }) {
56
59
  ensureMutable().delete(key);
57
60
  }
58
61
  }
59
- if (next) setExiting(next);
62
+ if (next) {
63
+ pendingExiting = next;
64
+ setExiting(next);
65
+ }
60
66
  }
67
+ const activeExiting = pendingExiting ?? exiting;
61
68
  const handleRemove = react.useCallback((key) => {
62
69
  setExiting((prev) => {
63
70
  if (!prev.has(key)) return prev;
@@ -66,19 +73,42 @@ function Presence({ children }) {
66
73
  return next;
67
74
  });
68
75
  }, []);
69
- const renderList = [];
76
+ const byKey = /* @__PURE__ */ new Map();
77
+ const presentKeys = /* @__PURE__ */ new Set();
78
+ const order = [];
70
79
  for (const el of incoming) {
71
- renderList.push({
72
- key: el.key,
73
- element: el,
74
- isPresent: true
75
- });
80
+ const key = el.key;
81
+ byKey.set(key, el);
82
+ presentKeys.add(key);
83
+ order.push(key);
76
84
  }
77
- for (const [key, el] of exiting) {
78
- if (!renderList.some((entry) => entry.key === key)) {
79
- renderList.push({ key, element: el, isPresent: false });
85
+ const prevOrder = orderRef.current;
86
+ for (let i = 0; i < prevOrder.length; i++) {
87
+ const key = prevOrder[i];
88
+ const departing = activeExiting.get(key);
89
+ if (!departing || byKey.has(key)) continue;
90
+ let insertAt = 0;
91
+ for (let j = i - 1; j >= 0; j--) {
92
+ const anchor = order.indexOf(prevOrder[j]);
93
+ if (anchor !== -1) {
94
+ insertAt = anchor + 1;
95
+ break;
96
+ }
80
97
  }
98
+ byKey.set(key, departing);
99
+ order.splice(insertAt, 0, key);
81
100
  }
101
+ for (const [key, el] of activeExiting) {
102
+ if (byKey.has(key)) continue;
103
+ byKey.set(key, el);
104
+ order.push(key);
105
+ }
106
+ orderRef.current = order;
107
+ const renderList = order.map((key) => ({
108
+ key,
109
+ element: byKey.get(key),
110
+ isPresent: presentKeys.has(key)
111
+ }));
82
112
  return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: renderList.map(({ key, element, isPresent }) => /* @__PURE__ */ jsxRuntime.jsx(
83
113
  PresenceItem,
84
114
  {
@@ -105,20 +135,189 @@ function PresenceItem({
105
135
  );
106
136
  return /* @__PURE__ */ jsxRuntime.jsx(PresenceContext.Provider, { value, children });
107
137
  }
138
+
139
+ // src/internal/boxShadow.ts
140
+ var LENGTH = /^[+-]?(\d+\.?\d*|\.\d+)(px)?$/i;
141
+ var UNIT_LIKE = /^[+-]?(\d+\.?\d*|\.\d+)[a-z%]+$/i;
142
+ function invalid(input, reason) {
143
+ return new Error(
144
+ `[inertia] parseBoxShadow: ${reason} in ${JSON.stringify(input)}. Expected CSS box-shadow syntax with px lengths: '[inset] <offset-x> <offset-y> [blur] [spread] [color], ...'`
145
+ );
146
+ }
147
+ function splitLayers(input) {
148
+ const layers = [];
149
+ let depth = 0;
150
+ let start = 0;
151
+ for (let i = 0; i < input.length; i++) {
152
+ const ch = input[i];
153
+ if (ch === "(") depth++;
154
+ else if (ch === ")") depth--;
155
+ else if (ch === "," && depth === 0) {
156
+ layers.push(input.slice(start, i));
157
+ start = i + 1;
158
+ }
159
+ }
160
+ layers.push(input.slice(start));
161
+ return layers;
162
+ }
163
+ function tokenize(layer) {
164
+ const tokens = [];
165
+ let depth = 0;
166
+ let current = "";
167
+ for (const ch of layer) {
168
+ if (ch === "(") depth++;
169
+ else if (ch === ")") depth--;
170
+ if (depth === 0 && /\s/.test(ch)) {
171
+ if (current) tokens.push(current);
172
+ current = "";
173
+ } else {
174
+ current += ch;
175
+ }
176
+ }
177
+ if (current) tokens.push(current);
178
+ return tokens;
179
+ }
180
+ function parseBoxShadow(input) {
181
+ const trimmed = input.trim();
182
+ if (trimmed === "") throw invalid(input, "empty string");
183
+ if (trimmed.toLowerCase() === "none") return [];
184
+ return splitLayers(trimmed).map((layerString) => {
185
+ const tokens = tokenize(layerString.trim());
186
+ if (tokens.length === 0) throw invalid(input, "empty layer");
187
+ const lengths = [];
188
+ let color;
189
+ let inset = false;
190
+ for (const token of tokens) {
191
+ if (token.toLowerCase() === "inset") {
192
+ if (inset) throw invalid(input, "duplicate 'inset'");
193
+ inset = true;
194
+ } else if (LENGTH.test(token)) {
195
+ lengths.push(parseFloat(token));
196
+ } else if (UNIT_LIKE.test(token)) {
197
+ throw invalid(input, `unsupported unit in ${JSON.stringify(token)}`);
198
+ } else {
199
+ if (color !== void 0) throw invalid(input, "multiple colors");
200
+ color = token;
201
+ }
202
+ }
203
+ if (lengths.length < 2 || lengths.length > 4) {
204
+ throw invalid(input, `expected 2-4 lengths, got ${lengths.length}`);
205
+ }
206
+ const [offsetX = 0, offsetY = 0, blurRadius = 0, spreadDistance = 0] = lengths;
207
+ if (blurRadius < 0) throw invalid(input, "negative blur radius");
208
+ return {
209
+ offsetX,
210
+ offsetY,
211
+ blurRadius,
212
+ spreadDistance,
213
+ color: color ?? "black",
214
+ inset
215
+ };
216
+ });
217
+ }
218
+ function resolveBoxShadowInput(input) {
219
+ if (input === void 0) return [];
220
+ if (typeof input === "string") return parseBoxShadow(input);
221
+ return input.map((layer) => ({
222
+ offsetX: coerceLength(layer.offsetX, "offsetX"),
223
+ offsetY: coerceLength(layer.offsetY, "offsetY"),
224
+ blurRadius: coerceLength(layer.blurRadius, "blurRadius"),
225
+ spreadDistance: coerceLength(layer.spreadDistance, "spreadDistance"),
226
+ color: layer.color ?? "black",
227
+ inset: layer.inset ?? false
228
+ }));
229
+ }
230
+ function pairBoxShadowLayers(from, to) {
231
+ const count = Math.max(from.length, to.length);
232
+ const pairs = [];
233
+ for (let i = 0; i < count; i++) {
234
+ const a = from[i];
235
+ const b = to[i];
236
+ const fromLayer = a ?? invisibleLayer(b.inset);
237
+ const toLayer = b ?? invisibleLayer(a.inset);
238
+ if (fromLayer.inset !== toLayer.inset) {
239
+ throw new Error(
240
+ `[inertia] useShadow: boxShadow layer ${i} is 'inset' on one side but not the other \u2014 inset cannot be interpolated. Give both sides the same inset-ness (pad with a transparent layer if needed).`
241
+ );
242
+ }
243
+ pairs.push({ from: fromLayer, to: toLayer });
244
+ }
245
+ return pairs;
246
+ }
247
+ function invisibleLayer(inset) {
248
+ return {
249
+ offsetX: 0,
250
+ offsetY: 0,
251
+ blurRadius: 0,
252
+ spreadDistance: 0,
253
+ color: "transparent",
254
+ inset
255
+ };
256
+ }
257
+ function coerceLength(value, field) {
258
+ if (value === void 0) return 0;
259
+ if (typeof value === "number") return value;
260
+ const trimmed = typeof value === "string" ? value.trim() : "";
261
+ if (!LENGTH.test(trimmed)) {
262
+ throw new Error(
263
+ `[inertia] boxShadow: ${field} must be a number or a px length, got ${JSON.stringify(value)}.`
264
+ );
265
+ }
266
+ return parseFloat(trimmed);
267
+ }
268
+ function strip(layer) {
269
+ const { inset: _inset, ...rest } = layer;
270
+ return rest;
271
+ }
272
+ function markInset(insets, i, count) {
273
+ const list = insets ?? new Array(count).fill(false);
274
+ list[i] = true;
275
+ return list;
276
+ }
277
+ function normalizeBoxShadow(input) {
278
+ const resolved = resolveBoxShadowInput(input);
279
+ const layers = [];
280
+ let insets = null;
281
+ for (let i = 0; i < resolved.length; i++) {
282
+ const layer = resolved[i];
283
+ layers.push(strip(layer));
284
+ if (layer.inset) insets = markInset(insets, i, resolved.length);
285
+ }
286
+ return { layers, insets };
287
+ }
288
+ function prepareBoxShadowAnimation(current, target) {
289
+ const pairs = pairBoxShadowLayers(
290
+ current.layers.map((layer, i) => ({
291
+ ...layer,
292
+ inset: current.insets?.[i] ?? false
293
+ })),
294
+ resolveBoxShadowInput(target)
295
+ );
296
+ const from = [];
297
+ const to = [];
298
+ let insets = null;
299
+ for (let i = 0; i < pairs.length; i++) {
300
+ const pair = pairs[i];
301
+ from.push(strip(pair.from));
302
+ to.push(strip(pair.to));
303
+ if (pair.to.inset) insets = markInset(insets, i, pairs.length);
304
+ }
305
+ return { from, to, insets };
306
+ }
108
307
  function resolveLayoutTransition(layout) {
109
308
  if (!layout) return void 0;
110
309
  const cfg = layout === true ? { type: "spring" } : layout;
111
310
  if (cfg.type === "no-animation") return void 0;
112
311
  if (cfg.type === "timing") {
113
312
  let builder2 = Animated.LinearTransition.duration(cfg.duration ?? 300);
114
- const easing = chunkPTRF47DA_js.ensureWorkletEasing(cfg.easing);
313
+ const easing = chunk7A6WTXNK_js.ensureWorkletEasing(cfg.easing);
115
314
  if (easing) builder2 = builder2.easing(easing);
116
315
  if (cfg.delay) builder2 = builder2.delay(cfg.delay);
117
316
  return builder2;
118
317
  }
119
318
  const spring = cfg.type === "decay" ? { type: "spring" } : cfg;
120
- const { stiffness, damping, mass } = chunkPTRF47DA_js.springToReanimated({
121
- ...chunkPTRF47DA_js.DEFAULT_SPRING,
319
+ const { stiffness, damping, mass } = chunk7A6WTXNK_js.springToReanimated({
320
+ ...chunk7A6WTXNK_js.DEFAULT_SPRING,
122
321
  ...spring
123
322
  });
124
323
  let builder = Animated.LinearTransition.springify().stiffness(stiffness).damping(damping).mass(mass);
@@ -130,68 +329,146 @@ function resolveLayoutTransition(layout) {
130
329
  var REGISTRY = /* @__PURE__ */ new Map();
131
330
  var SHARED_LAYOUT_TTL_MS = 1e3;
132
331
  var now = () => Date.now();
133
- function registerLayout(id, rect) {
134
- REGISTRY.set(id, { rect, expiresAt: now() + SHARED_LAYOUT_TTL_MS });
332
+ var lastSweep = 0;
333
+ function sweepExpired(at) {
334
+ if (at - lastSweep < SHARED_LAYOUT_TTL_MS) return;
335
+ lastSweep = at;
336
+ for (const [id, entry] of REGISTRY) {
337
+ if (entry.expiresAt < at) REGISTRY.delete(id);
338
+ }
135
339
  }
136
- function releaseLayout(id, rect) {
137
- REGISTRY.set(id, { rect, expiresAt: now() + SHARED_LAYOUT_TTL_MS });
340
+ function registerLayout(id, rect, remeasure, readStyles) {
341
+ const at = now();
342
+ sweepExpired(at);
343
+ REGISTRY.set(id, {
344
+ rect,
345
+ expiresAt: at + SHARED_LAYOUT_TTL_MS,
346
+ remeasure,
347
+ readStyles
348
+ });
349
+ }
350
+ function releaseLayout(id, rect, styles) {
351
+ const at = now();
352
+ sweepExpired(at);
353
+ REGISTRY.set(id, { rect, expiresAt: at + SHARED_LAYOUT_TTL_MS, styles });
138
354
  }
139
355
  function consumeLayout(id) {
140
356
  const entry = REGISTRY.get(id);
141
357
  if (!entry) return void 0;
142
358
  REGISTRY.delete(id);
143
359
  if (entry.expiresAt < now()) return void 0;
144
- return entry.rect;
360
+ return {
361
+ rect: entry.rect,
362
+ remeasure: entry.remeasure,
363
+ styles: entry.styles,
364
+ readStyles: entry.readStyles
365
+ };
366
+ }
367
+
368
+ // src/layout/measureWindow.ts
369
+ var defaultMeasurer = (node) => {
370
+ const measure = node?.measureInWindow;
371
+ if (typeof measure !== "function") return void 0;
372
+ let result;
373
+ let returned = false;
374
+ try {
375
+ measure.call(node, (x, y, width, height) => {
376
+ if (returned) return;
377
+ result = { x, y, width, height };
378
+ });
379
+ } catch {
380
+ returned = true;
381
+ return void 0;
382
+ }
383
+ returned = true;
384
+ return result;
385
+ };
386
+ var measurer = defaultMeasurer;
387
+ function usable(rect) {
388
+ const { x, y, width, height } = rect;
389
+ for (const v of [x, y, width, height]) {
390
+ if (typeof v !== "number" || !Number.isFinite(v)) return false;
391
+ }
392
+ return width !== 0 || height !== 0;
393
+ }
394
+ function measureWindowRect(node) {
395
+ const measured = measurer(node);
396
+ if (!measured || !usable(measured)) return void 0;
397
+ return toSharedRect(measured, "window");
398
+ }
399
+ function toSharedRect(rect, space) {
400
+ return { ...rect, space };
145
401
  }
146
402
  function useSharedLayout(options) {
147
- const { layoutId, userRef, transition, shouldReduceMotion, userOnLayout } = options;
403
+ const {
404
+ layoutId,
405
+ userRef,
406
+ transition,
407
+ shouldReduceMotion,
408
+ userOnLayout,
409
+ readStyles
410
+ } = options;
148
411
  const dx = Animated.useSharedValue(0);
149
412
  const dy = Animated.useSharedValue(0);
150
413
  const sx = Animated.useSharedValue(1);
151
414
  const sy = Animated.useSharedValue(1);
415
+ const snapshot = Animated.useSharedValue(null);
416
+ const carryProgress = Animated.useSharedValue(0);
152
417
  const lastRectRef = react.useRef(null);
153
418
  const consumedRef = react.useRef(false);
419
+ const nodeRef = react.useRef(null);
154
420
  const transitionRef = react.useRef(transition);
155
421
  transitionRef.current = transition;
156
422
  const reducedMotionRef = react.useRef(shouldReduceMotion);
157
423
  reducedMotionRef.current = shouldReduceMotion;
424
+ const readStylesRef = react.useRef(readStyles);
425
+ readStylesRef.current = readStyles;
158
426
  const setRef = react.useCallback(
159
427
  (node) => {
428
+ nodeRef.current = node;
160
429
  if (typeof userRef === "function") userRef(node);
161
430
  else if (userRef) userRef.current = node;
162
431
  },
163
432
  [userRef]
164
433
  );
434
+ const remeasure = react.useCallback(() => measureWindowRect(nodeRef.current), []);
435
+ const snapshotStyles = react.useCallback(() => readStylesRef.current?.(), []);
436
+ const startTransition = react.useCallback(
437
+ (source, sourceRect, target) => {
438
+ if (sourceRect.space !== target.space) return;
439
+ const shared = {
440
+ transition: transitionRef.current,
441
+ shouldReduceMotion: reducedMotionRef.current
442
+ };
443
+ applyFlip({ source: sourceRect, target, dx, dy, sx, sy, ...shared });
444
+ applyStyleCarry({
445
+ snapshot,
446
+ progress: carryProgress,
447
+ // Prefer a live read for the same reason the rect is re-measured: a
448
+ // still-mounted source may have moved on since its last layout.
449
+ styles: source.readStyles?.() ?? source.styles,
450
+ ...shared
451
+ });
452
+ },
453
+ [dx, dy, sx, sy, snapshot, carryProgress]
454
+ );
165
455
  const onLayout = react.useCallback(
166
456
  (event) => {
167
457
  userOnLayout?.(event);
168
458
  if (!layoutId) return;
169
459
  const { x, y, width, height } = event.nativeEvent.layout;
170
- const rect = { x, y, width, height };
171
- lastRectRef.current = rect;
172
460
  let source;
173
461
  if (!consumedRef.current) {
174
462
  consumedRef.current = true;
175
463
  source = consumeLayout(layoutId);
176
464
  }
177
- registerLayout(layoutId, rect);
178
- if (source) {
179
- applyFlip({
180
- source,
181
- target: rect,
182
- dx,
183
- dy,
184
- sx,
185
- sy,
186
- transition: transitionRef.current,
187
- shouldReduceMotion: reducedMotionRef.current
188
- });
189
- }
465
+ const rect = measureWindowRect(nodeRef.current) ?? { x, y, width, height, space: "parent" };
466
+ lastRectRef.current = rect;
467
+ registerLayout(layoutId, rect, remeasure, snapshotStyles);
468
+ if (!source) return;
469
+ startTransition(source, source.remeasure?.() ?? source.rect, rect);
190
470
  },
191
- // dx/dy/sx/sy are stable refs from useSharedValue, but eslint's
192
- // exhaustive-deps would flag them — including them is harmless and
193
- // silences the warning.
194
- [layoutId, userOnLayout, dx, dy, sx, sy]
471
+ [layoutId, userOnLayout, remeasure, snapshotStyles, startTransition]
195
472
  );
196
473
  react.useEffect(() => {
197
474
  consumedRef.current = false;
@@ -201,18 +478,49 @@ function useSharedLayout(options) {
201
478
  if (!layoutId) return;
202
479
  const rect = lastRectRef.current;
203
480
  if (!rect) return;
204
- releaseLayout(layoutId, rect);
481
+ releaseLayout(layoutId, rect, snapshotStyles());
205
482
  };
206
- }, [layoutId]);
483
+ }, [layoutId, snapshotStyles]);
484
+ react.useEffect(
485
+ () => () => {
486
+ Animated.cancelAnimation(dx);
487
+ Animated.cancelAnimation(dy);
488
+ Animated.cancelAnimation(sx);
489
+ Animated.cancelAnimation(sy);
490
+ Animated.cancelAnimation(carryProgress);
491
+ },
492
+ // The FLIP shared values are identity-stable per hook instance.
493
+ // eslint-disable-next-line react-hooks/exhaustive-deps
494
+ []
495
+ );
207
496
  return react.useMemo(
208
497
  () => ({
209
498
  flip: { dx, dy, sx, sy },
499
+ carry: { snapshot, progress: carryProgress },
210
500
  setRef,
211
501
  onLayout
212
502
  }),
213
- [dx, dy, sx, sy, setRef, onLayout]
503
+ [dx, dy, sx, sy, snapshot, carryProgress, setRef, onLayout]
504
+ );
505
+ }
506
+ function legBuilder(transition) {
507
+ if (transition?.type === "timing") {
508
+ const duration = transition.duration ?? 300;
509
+ return (from, to) => Animated.withSequence(
510
+ Animated.withTiming(from, { duration: 0 }),
511
+ Animated.withTiming(to, { duration })
512
+ );
513
+ }
514
+ const springCfg = transition?.type === "spring" ? { ...chunk7A6WTXNK_js.DEFAULT_SPRING, ...transition } : { type: "spring", ...chunk7A6WTXNK_js.DEFAULT_SPRING };
515
+ const springParams = chunk7A6WTXNK_js.springToReanimated(springCfg);
516
+ return (from, to) => Animated.withSequence(
517
+ Animated.withTiming(from, { duration: 0 }),
518
+ Animated.withSpring(to, springParams)
214
519
  );
215
520
  }
521
+ function shouldSnap(transition, shouldReduceMotion) {
522
+ return shouldReduceMotion || transition?.type === "no-animation";
523
+ }
216
524
  function applyFlip(args) {
217
525
  const { source, target, dx, dy, sx, sy, transition, shouldReduceMotion } = args;
218
526
  const sourceCenterX = source.x + source.width / 2;
@@ -223,58 +531,29 @@ function applyFlip(args) {
223
531
  const deltaY = sourceCenterY - targetCenterY;
224
532
  const scaleX = target.width > 0 ? source.width / target.width : 1;
225
533
  const scaleY = target.height > 0 ? source.height / target.height : 1;
226
- if (shouldReduceMotion) {
534
+ if (shouldSnap(transition, shouldReduceMotion)) {
227
535
  dx.value = 0;
228
536
  dy.value = 0;
229
537
  sx.value = 1;
230
538
  sy.value = 1;
231
539
  return;
232
540
  }
233
- if (transition?.type === "no-animation") {
234
- dx.value = 0;
235
- dy.value = 0;
236
- sx.value = 1;
237
- sy.value = 1;
238
- return;
239
- }
240
- if (transition?.type === "timing") {
241
- const duration = transition.duration ?? 300;
242
- dx.value = Animated.withSequence(
243
- Animated.withTiming(deltaX, { duration: 0 }),
244
- Animated.withTiming(0, { duration })
245
- );
246
- dy.value = Animated.withSequence(
247
- Animated.withTiming(deltaY, { duration: 0 }),
248
- Animated.withTiming(0, { duration })
249
- );
250
- sx.value = Animated.withSequence(
251
- Animated.withTiming(scaleX, { duration: 0 }),
252
- Animated.withTiming(1, { duration })
253
- );
254
- sy.value = Animated.withSequence(
255
- Animated.withTiming(scaleY, { duration: 0 }),
256
- Animated.withTiming(1, { duration })
257
- );
541
+ const leg = legBuilder(transition);
542
+ dx.value = leg(deltaX, 0);
543
+ dy.value = leg(deltaY, 0);
544
+ sx.value = leg(scaleX, 1);
545
+ sy.value = leg(scaleY, 1);
546
+ }
547
+ function applyStyleCarry(args) {
548
+ const { snapshot, progress, styles, transition, shouldReduceMotion } = args;
549
+ if (!styles) return;
550
+ if (shouldSnap(transition, shouldReduceMotion)) {
551
+ snapshot.value = null;
552
+ progress.value = 0;
258
553
  return;
259
554
  }
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
- dx.value = Animated.withSequence(
263
- Animated.withTiming(deltaX, { duration: 0 }),
264
- Animated.withSpring(0, springParams)
265
- );
266
- dy.value = Animated.withSequence(
267
- Animated.withTiming(deltaY, { duration: 0 }),
268
- Animated.withSpring(0, springParams)
269
- );
270
- sx.value = Animated.withSequence(
271
- Animated.withTiming(scaleX, { duration: 0 }),
272
- Animated.withSpring(1, springParams)
273
- );
274
- sy.value = Animated.withSequence(
275
- Animated.withTiming(scaleY, { duration: 0 }),
276
- Animated.withSpring(1, springParams)
277
- );
555
+ snapshot.value = styles;
556
+ progress.value = legBuilder(transition)(1, 0);
278
557
  }
279
558
  var alreadyChecked = false;
280
559
  function ensureReanimatedInstalled() {
@@ -288,7 +567,7 @@ function ensureReanimatedInstalled() {
288
567
  const major = parseInt(version.split(".")[0] ?? "0", 10);
289
568
  if (major < 4) {
290
569
  console.error(
291
- `[inertia] react-native-reanimated v${version} is installed, but @rootnative/inertia requires v4.0.0 or later. Upgrade with \`pnpm add react-native-reanimated@^4\` (or your package manager's equivalent).`
570
+ `[inertia] react-native-reanimated ${version} is installed, but @rootnative/inertia requires 4.0.0 or later. Upgrade with \`pnpm add react-native-reanimated@^4\` (or your package manager's equivalent).`
292
571
  );
293
572
  return;
294
573
  }
@@ -331,15 +610,28 @@ var COLOR_KEYS = [
331
610
  "shadowColor"
332
611
  ];
333
612
  var SHADOW_OFFSET_KEYS = ["shadowOffsetWidth", "shadowOffsetHeight"];
613
+ var STRUCTURED_KEYS = ["boxShadow"];
614
+ var SHARED_STYLE_KEYS = [
615
+ "opacity",
616
+ "borderRadius",
617
+ "backgroundColor",
618
+ "borderColor",
619
+ "color",
620
+ "tintColor"
621
+ ];
334
622
  var ALL_KEYS = [
335
623
  ...TRANSFORM_KEYS,
336
624
  ...NUMERIC_TOP_LEVEL_KEYS,
337
625
  ...COLOR_KEYS,
338
- ...SHADOW_OFFSET_KEYS
626
+ ...SHADOW_OFFSET_KEYS,
627
+ ...STRUCTURED_KEYS
339
628
  ];
340
629
  var TRANSFORM_KEY_SET = new Set(TRANSFORM_KEYS);
341
630
  var COLOR_KEY_SET = new Set(COLOR_KEYS);
342
631
  var SHADOW_OFFSET_KEY_SET = new Set(SHADOW_OFFSET_KEYS);
632
+ var STRUCTURED_KEY_SET = new Set(STRUCTURED_KEYS);
633
+ var SHARED_STYLE_KEY_SET = new Set(SHARED_STYLE_KEYS);
634
+ var NO_BOX_SHADOW = Object.freeze([]);
343
635
  var GESTURE_LAYER_NAMES = [
344
636
  "hovered",
345
637
  "focused",
@@ -374,19 +666,20 @@ var DEFAULT_RESTING = {
374
666
  tintColor: "transparent",
375
667
  shadowColor: "transparent",
376
668
  shadowOffsetWidth: 0,
377
- shadowOffsetHeight: 0
669
+ shadowOffsetHeight: 0,
670
+ boxShadow: NO_BOX_SHADOW
378
671
  };
379
672
  function transitionFor(prop, transition) {
380
673
  if (!transition) return void 0;
381
674
  if (typeof transition === "string") return void 0;
382
- if (chunkPTRF47DA_js.isTopLevelTransition(transition)) return transition;
675
+ if (chunk7A6WTXNK_js.isTopLevelTransition(transition)) return transition;
383
676
  if (GESTURE_LAYER_NAME_SET.has(prop)) return void 0;
384
677
  return transition[prop];
385
678
  }
386
679
  function gestureLayerTransitionFor(layer, transition) {
387
680
  if (!transition) return void 0;
388
681
  if (typeof transition === "string") return void 0;
389
- if (chunkPTRF47DA_js.isTopLevelTransition(transition)) return transition;
682
+ if (chunk7A6WTXNK_js.isTopLevelTransition(transition)) return transition;
390
683
  return transition[layer];
391
684
  }
392
685
  function createMotionComponent(Component) {
@@ -436,12 +729,12 @@ function createMotionComponent(Component) {
436
729
  onLayout: userOnLayout,
437
730
  ...rest
438
731
  } = props;
439
- const namedTransitions = chunk7AOERN53_js.useNamedTransitions();
440
- const transition = chunk7AOERN53_js.resolveNamedTransitionProp(
732
+ const namedTransitions = chunkWVRCKOPO_js.useNamedTransitions();
733
+ const transition = chunkWVRCKOPO_js.resolveNamedTransitionProp(
441
734
  transitionProp,
442
735
  namedTransitions
443
736
  );
444
- const layout = typeof layoutProp === "string" ? chunk7AOERN53_js.lookupNamedTransition(layoutProp, namedTransitions) : layoutProp;
737
+ const layout = typeof layoutProp === "string" ? chunkWVRCKOPO_js.lookupNamedTransition(layoutProp, namedTransitions) : layoutProp;
445
738
  if (__DEV__ && typeof style === "function") {
446
739
  throw new Error(
447
740
  "[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."
@@ -449,7 +742,7 @@ function createMotionComponent(Component) {
449
742
  }
450
743
  const presence = usePresence();
451
744
  const isExiting = presence !== null && presence.isPresent === false;
452
- const shouldReduceMotion = chunk7AOERN53_js.useShouldReduceMotion();
745
+ const shouldReduceMotion = chunkWVRCKOPO_js.useShouldReduceMotion();
453
746
  const onAnimationEndRef = react.useRef(onAnimationEnd);
454
747
  onAnimationEndRef.current = onAnimationEnd;
455
748
  const variantKey = useControllerKey(controller);
@@ -465,6 +758,16 @@ function createMotionComponent(Component) {
465
758
  const [focused, setFocused] = react.useState(false);
466
759
  const [focusVisible, setFocusVisible] = react.useState(false);
467
760
  const [hovered, setHovered] = react.useState(false);
761
+ const hasLayoutId = layoutId !== void 0;
762
+ let flatStyle;
763
+ let flatStyleRead = false;
764
+ const getFlatStyle = () => {
765
+ if (!flatStyleRead) {
766
+ flatStyleRead = true;
767
+ flatStyle = reactNative.StyleSheet.flatten(style);
768
+ }
769
+ return flatStyle;
770
+ };
468
771
  const touched = /* @__PURE__ */ new Set();
469
772
  collectTouchedKeys(touched, animateRecord);
470
773
  if (initialRecord) collectTouchedKeys(touched, initialRecord);
@@ -486,9 +789,19 @@ function createMotionComponent(Component) {
486
789
  }
487
790
  }
488
791
  if (exitRecord) collectTouchedKeys(touched, exitRecord);
792
+ if (hasLayoutId) {
793
+ const flat = getFlatStyle();
794
+ if (flat) {
795
+ for (const key of SHARED_STYLE_KEYS) {
796
+ if (touched.has(key)) continue;
797
+ if (styleValueFor(flat, key) !== void 0) touched.add(key);
798
+ }
799
+ }
800
+ }
489
801
  const activeKeysRef = react.useRef(null);
490
802
  const hasTransformRef = react.useRef(false);
491
803
  const hasShadowOffsetRef = react.useRef(false);
804
+ const hasBoxShadowRef = react.useRef(false);
492
805
  const prevActive = activeKeysRef.current;
493
806
  let grew = prevActive === null;
494
807
  if (!grew && prevActive) {
@@ -509,24 +822,83 @@ function createMotionComponent(Component) {
509
822
  hasShadowOffsetRef.current = activeKeysRef.current.some(
510
823
  (k) => SHADOW_OFFSET_KEY_SET.has(k)
511
824
  );
825
+ hasBoxShadowRef.current = activeKeysRef.current.includes("boxShadow");
826
+ if (__DEV__ && hasBoxShadowRef.current && activeKeysRef.current.some(
827
+ (k) => k !== "boxShadow" && k.startsWith("shadow")
828
+ )) {
829
+ chunk7A6WTXNK_js.warnOnce(
830
+ "boxShadow-with-native-shadow",
831
+ "[inertia] `boxShadow` is animated alongside the native `shadow*` keys on the same element, which applies two shadow systems at once. Pick one: `boxShadow` for the cross-platform CSS form, or the native `shadow*` keys."
832
+ );
833
+ }
834
+ }
835
+ const drivenNow = /* @__PURE__ */ new Set();
836
+ collectTouchedKeys(drivenNow, animateRecord);
837
+ if (initialRecord) collectTouchedKeys(drivenNow, initialRecord);
838
+ if (isExiting && exitRecord) collectTouchedKeys(drivenNow, exitRecord);
839
+ const everDrivenRef = react.useRef(/* @__PURE__ */ new Set());
840
+ for (const k of drivenNow) everDrivenRef.current.add(k);
841
+ const activeKeys = activeKeysRef.current;
842
+ const everDriven = everDrivenRef.current;
843
+ const styleResting = {};
844
+ let styleRestingShadow = null;
845
+ if (activeKeys.some((k) => !everDriven.has(k))) {
846
+ const flat = getFlatStyle();
847
+ if (flat) {
848
+ for (const key of activeKeys) {
849
+ if (everDriven.has(key)) continue;
850
+ if (key === "boxShadow") {
851
+ const raw = flat.boxShadow;
852
+ if (raw !== void 0) {
853
+ styleRestingShadow = normalizeBoxShadow(raw);
854
+ styleResting.boxShadow = styleRestingShadow.layers;
855
+ }
856
+ continue;
857
+ }
858
+ const v = styleValueFor(flat, key);
859
+ if (v !== void 0) styleResting[key] = v;
860
+ }
861
+ }
862
+ }
863
+ const boxShadowSeedRef = react.useRef(null);
864
+ if (boxShadowSeedRef.current === null) {
865
+ const source = initial === false ? animateRecord.boxShadow : initialRecord?.boxShadow ?? animateRecord.boxShadow;
866
+ boxShadowSeedRef.current = source !== void 0 ? normalizeBoxShadow(source) : styleRestingShadow ?? {
867
+ layers: [...NO_BOX_SHADOW],
868
+ insets: null
869
+ };
512
870
  }
513
871
  const sharedValues = useAnimatableSharedValues((key) => {
872
+ if (key === "boxShadow") return boxShadowSeedRef.current.layers;
514
873
  if (SHADOW_OFFSET_KEY_SET.has(key)) {
515
874
  const axis = shadowOffsetAxisFor(key);
516
875
  if (initial === false) {
517
- return shadowOffsetAxisValue(animateRecord.shadowOffset, axis) ?? DEFAULT_RESTING[key];
876
+ return shadowOffsetAxisValue(animateRecord.shadowOffset, axis) ?? styleResting[key] ?? DEFAULT_RESTING[key];
518
877
  }
519
878
  return shadowOffsetAxisValue(
520
879
  initialRecord?.shadowOffset,
521
880
  axis
522
- ) ?? shadowOffsetAxisValue(animateRecord.shadowOffset, axis) ?? DEFAULT_RESTING[key];
881
+ ) ?? shadowOffsetAxisValue(animateRecord.shadowOffset, axis) ?? styleResting[key] ?? DEFAULT_RESTING[key];
523
882
  }
524
883
  if (initial === false) {
525
884
  const a = animateRecord[key];
526
- return restValue(a) ?? DEFAULT_RESTING[key];
885
+ return restValue(a) ?? styleResting[key] ?? DEFAULT_RESTING[key];
527
886
  }
528
- return initialRecord?.[key] ?? restValue(animateRecord[key]) ?? DEFAULT_RESTING[key];
887
+ return initialRecord?.[key] ?? restValue(animateRecord[key]) ?? styleResting[key] ?? DEFAULT_RESTING[key];
529
888
  });
889
+ const boxShadowInsets = Animated.useSharedValue(
890
+ boxShadowSeedRef.current.insets
891
+ );
892
+ const styleRestingSig = chunk7A6WTXNK_js.stableSig(styleResting);
893
+ react.useEffect(() => {
894
+ for (const key of activeKeysRef.current) {
895
+ if (everDrivenRef.current.has(key)) continue;
896
+ sharedValues[key].value = styleResting[key] ?? DEFAULT_RESTING[key];
897
+ if (key === "boxShadow") {
898
+ boxShadowInsets.value = styleRestingShadow?.insets ?? null;
899
+ }
900
+ }
901
+ }, [styleRestingSig]);
530
902
  const pressedProgress = Animated.useSharedValue(0);
531
903
  const focusedProgress = Animated.useSharedValue(0);
532
904
  const focusVisibleProgress = Animated.useSharedValue(0);
@@ -545,13 +917,13 @@ function createMotionComponent(Component) {
545
917
  const gestureSV = Animated.useSharedValue(
546
918
  resolveGestureLayers(gesture)
547
919
  );
548
- const gestureTargetsSig = chunkPTRF47DA_js.stableSig(gesture);
920
+ const gestureTargetsSig = chunk7A6WTXNK_js.stableSig(gesture);
549
921
  react.useEffect(() => {
550
922
  gestureSV.value = resolveGestureLayers(gesture);
551
923
  }, [gestureTargetsSig]);
552
924
  const baseRecord = isExiting && exitRecord ? { ...animateRecord, ...exitRecord } : animateRecord;
553
- const baseSig = chunkPTRF47DA_js.stableSig(baseRecord) + (isExiting ? "|exit" : "") + (shouldReduceMotion ? "|rm" : "");
554
- const transitionSig = chunkPTRF47DA_js.stableSig(transition);
925
+ const baseSig = chunk7A6WTXNK_js.stableSig(baseRecord) + (isExiting ? "|exit" : "") + (shouldReduceMotion ? "|rm" : "");
926
+ const transitionSig = chunk7A6WTXNK_js.stableSig(transition);
555
927
  const safeToRemoveRef = react.useRef(void 0);
556
928
  safeToRemoveRef.current = presence?.safeToRemove;
557
929
  react.useEffect(() => {
@@ -569,24 +941,49 @@ function createMotionComponent(Component) {
569
941
  if (isExiting) safeToRemoveRef.current?.();
570
942
  }
571
943
  };
944
+ const configFor = (key) => shouldReduceMotion ? { type: "no-animation" } : transitionFor(
945
+ SHADOW_OFFSET_KEY_SET.has(key) ? "shadowOffset" : key,
946
+ transition
947
+ );
572
948
  let transformPending = 0;
573
949
  for (const k of ALL_KEYS) {
574
- if (TRANSFORM_KEY_SET.has(k) && baseRecord[k] !== void 0) {
575
- transformPending++;
576
- }
950
+ if (!TRANSFORM_KEY_SET.has(k) || baseRecord[k] === void 0) continue;
951
+ if (!reachesTerminalPhase(configFor(k))) continue;
952
+ transformPending++;
577
953
  }
578
954
  const transformGroup = transformPending > 0 ? { remaining: transformPending } : void 0;
579
955
  for (const key of ALL_KEYS) {
956
+ if (key === "boxShadow") {
957
+ const shadowTarget = baseRecord.boxShadow;
958
+ if (shadowTarget === void 0) continue;
959
+ const cfg2 = configFor("boxShadow");
960
+ if (isExiting && reachesTerminalPhase(cfg2)) pending++;
961
+ driveBoxShadow(
962
+ sharedValues.boxShadow,
963
+ boxShadowInsets,
964
+ shadowTarget,
965
+ cfg2,
966
+ makeKeyCallbackFactory(
967
+ "boxShadow",
968
+ sharedValues.boxShadow,
969
+ // The declared target, not the padded one — the padding is an
970
+ // implementation detail of getting Reanimated to interpolate.
971
+ shadowTarget,
972
+ onAnimationEndRef,
973
+ { stepCount: 1, totalIterations: totalIterationsOf(cfg2) },
974
+ isExiting ? onSettle : void 0,
975
+ void 0
976
+ )
977
+ );
978
+ continue;
979
+ }
580
980
  const target = SHADOW_OFFSET_KEY_SET.has(key) ? shadowOffsetAxisValue(
581
981
  baseRecord.shadowOffset,
582
982
  shadowOffsetAxisFor(key)
583
983
  ) : baseRecord[key];
584
984
  if (target === void 0) continue;
585
- const cfg = shouldReduceMotion ? { type: "no-animation" } : transitionFor(
586
- SHADOW_OFFSET_KEY_SET.has(key) ? "shadowOffset" : key,
587
- transition
588
- );
589
- if (isExiting) pending++;
985
+ const cfg = configFor(key);
986
+ if (isExiting && reachesTerminalPhase(cfg)) pending++;
590
987
  const factory = makeKeyCallbackFactory(
591
988
  key,
592
989
  sharedValues[key],
@@ -599,7 +996,7 @@ function createMotionComponent(Component) {
599
996
  isExiting ? onSettle : void 0,
600
997
  TRANSFORM_KEY_SET.has(key) ? transformGroup : void 0
601
998
  );
602
- sharedValues[key].value = chunkPTRF47DA_js.resolveAnimatableValue(
999
+ sharedValues[key].value = chunk7A6WTXNK_js.resolveAnimatableValue(
603
1000
  target,
604
1001
  cfg,
605
1002
  factory
@@ -645,19 +1042,34 @@ function createMotionComponent(Component) {
645
1042
  isExiting,
646
1043
  shouldReduceMotion
647
1044
  );
1045
+ const readSharedStyles = () => {
1046
+ if (!hasLayoutId) return void 0;
1047
+ const out = {};
1048
+ let any = false;
1049
+ for (const key of activeKeysRef.current) {
1050
+ if (!SHARED_STYLE_KEY_SET.has(key)) continue;
1051
+ const v = sharedValues[key].value;
1052
+ if (typeof v !== "number" && typeof v !== "string") continue;
1053
+ out[key] = v;
1054
+ any = true;
1055
+ }
1056
+ return any ? out : void 0;
1057
+ };
648
1058
  const sharedLayout = useSharedLayout({
649
1059
  layoutId,
650
1060
  userRef: ref,
651
- transition: chunkPTRF47DA_js.isTopLevelTransition(transition) ? transition : void 0,
1061
+ transition: chunk7A6WTXNK_js.isTopLevelTransition(transition) ? transition : void 0,
652
1062
  shouldReduceMotion,
653
- userOnLayout
1063
+ userOnLayout,
1064
+ readStyles: readSharedStyles
654
1065
  });
655
1066
  const flip = sharedLayout.flip;
656
- const hasLayoutId = layoutId !== void 0;
1067
+ const carry = sharedLayout.carry;
657
1068
  const animatedStyle = Animated.useAnimatedStyle(() => {
658
- const activeKeys = activeKeysRef.current;
1069
+ const activeKeys2 = activeKeysRef.current;
659
1070
  const hasTransform = hasTransformRef.current;
660
1071
  const hasShadowOffset = hasShadowOffsetRef.current;
1072
+ const hasBoxShadow = hasBoxShadowRef.current;
661
1073
  const out = {};
662
1074
  const transform = [];
663
1075
  let shadowOffsetW = 0;
@@ -666,12 +1078,15 @@ function createMotionComponent(Component) {
666
1078
  const pf = focusedProgress.value;
667
1079
  const pfv = focusVisibleProgress.value;
668
1080
  const pp = pressedProgress.value;
1081
+ const carried = carry.snapshot.value;
1082
+ const pc = carry.progress.value;
669
1083
  const layers = gestureSV.value;
670
1084
  const hoveredLayer = layers ? layers.hovered : null;
671
1085
  const focusedLayer = layers ? layers.focused : null;
672
1086
  const focusVisibleLayer = layers ? layers.focusVisible : null;
673
1087
  const pressedLayer = layers ? layers.pressed : null;
674
- for (const key of activeKeys) {
1088
+ for (const key of activeKeys2) {
1089
+ if (key === "boxShadow") continue;
675
1090
  let v = sharedValues[key].value;
676
1091
  const isColor = COLOR_KEY_SET.has(key);
677
1092
  if (hoveredLayer && ph > 0 && hoveredLayer[key] !== void 0) {
@@ -690,6 +1105,12 @@ function createMotionComponent(Component) {
690
1105
  const t = pressedLayer[key];
691
1106
  v = isColor ? Animated.interpolateColor(pp, [0, 1], [v, t]) : v + (t - v) * pp;
692
1107
  }
1108
+ if (carried !== null && pc > 0) {
1109
+ const s = carried[key];
1110
+ if (s !== void 0) {
1111
+ v = isColor ? Animated.interpolateColor(pc, [0, 1], [v, s]) : v + (s - v) * pc;
1112
+ }
1113
+ }
693
1114
  if (TRANSFORM_KEY_SET.has(key)) {
694
1115
  transform.push(
695
1116
  ROTATION_KEYS.has(key) ? { [key]: `${v}deg` } : { [key]: v }
@@ -712,6 +1133,19 @@ function createMotionComponent(Component) {
712
1133
  if (hasShadowOffset) {
713
1134
  out.shadowOffset = { width: shadowOffsetW, height: shadowOffsetH };
714
1135
  }
1136
+ if (hasBoxShadow) {
1137
+ const layers2 = sharedValues.boxShadow.value;
1138
+ const insets = boxShadowInsets.value;
1139
+ if (insets === null) {
1140
+ out.boxShadow = layers2;
1141
+ } else {
1142
+ const withInset = [];
1143
+ for (let i = 0; i < layers2.length; i++) {
1144
+ withInset.push({ ...layers2[i], inset: insets[i] });
1145
+ }
1146
+ out.boxShadow = withInset;
1147
+ }
1148
+ }
715
1149
  return out;
716
1150
  });
717
1151
  const mergedStyle = react.useMemo(
@@ -726,7 +1160,7 @@ function createMotionComponent(Component) {
726
1160
  setFocusVisible,
727
1161
  setHovered
728
1162
  );
729
- const layoutSig = chunkPTRF47DA_js.stableSig(layout);
1163
+ const layoutSig = chunk7A6WTXNK_js.stableSig(layout);
730
1164
  const layoutTransition = react.useMemo(
731
1165
  () => shouldReduceMotion ? void 0 : resolveLayoutTransition(layout),
732
1166
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -786,7 +1220,9 @@ function useAnimatableSharedValues(init) {
786
1220
  const width = Animated.useSharedValue(init("width"));
787
1221
  const height = Animated.useSharedValue(init("height"));
788
1222
  const borderRadius = Animated.useSharedValue(init("borderRadius"));
789
- const shadowOpacity = Animated.useSharedValue(init("shadowOpacity"));
1223
+ const shadowOpacity = Animated.useSharedValue(
1224
+ init("shadowOpacity")
1225
+ );
790
1226
  const shadowRadius = Animated.useSharedValue(init("shadowRadius"));
791
1227
  const elevation = Animated.useSharedValue(init("elevation"));
792
1228
  const backgroundColor = Animated.useSharedValue(
@@ -802,6 +1238,7 @@ function useAnimatableSharedValues(init) {
802
1238
  const shadowOffsetHeight = Animated.useSharedValue(
803
1239
  init("shadowOffsetHeight")
804
1240
  );
1241
+ const boxShadow = Animated.useSharedValue(init("boxShadow"));
805
1242
  const ref = react.useRef(null);
806
1243
  if (ref.current === null) {
807
1244
  ref.current = {
@@ -826,7 +1263,8 @@ function useAnimatableSharedValues(init) {
826
1263
  tintColor,
827
1264
  shadowColor,
828
1265
  shadowOffsetWidth,
829
- shadowOffsetHeight
1266
+ shadowOffsetHeight,
1267
+ boxShadow
830
1268
  };
831
1269
  }
832
1270
  const map = ref.current;
@@ -911,6 +1349,54 @@ function shadowOffsetAxisFor(key) {
911
1349
  function shadowOffsetAxisValue(source, axis) {
912
1350
  return source?.[axis];
913
1351
  }
1352
+ function driveBoxShadow(slot, insetSlot, target, cfg, factory) {
1353
+ const currentLayers = Array.isArray(slot.value) ? slot.value : NO_BOX_SHADOW;
1354
+ const { from, to, insets } = prepareBoxShadowAnimation(
1355
+ { layers: [...currentLayers], insets: insetSlot.value },
1356
+ target
1357
+ );
1358
+ insetSlot.value = insets;
1359
+ if (from.length !== currentLayers.length) slot.value = from;
1360
+ slot.value = chunk7A6WTXNK_js.resolveTransition(
1361
+ cfg,
1362
+ to,
1363
+ factory?.("animation", void 0)
1364
+ );
1365
+ }
1366
+ function styleValueFor(flat, key) {
1367
+ if (SHADOW_OFFSET_KEY_SET.has(key)) {
1368
+ return shadowOffsetAxisValue(
1369
+ flat.shadowOffset,
1370
+ shadowOffsetAxisFor(key)
1371
+ );
1372
+ }
1373
+ if (TRANSFORM_KEY_SET.has(key)) {
1374
+ const list = flat.transform;
1375
+ if (!Array.isArray(list)) return void 0;
1376
+ for (const entry of list) {
1377
+ if (!entry || typeof entry !== "object") continue;
1378
+ const v2 = entry[key];
1379
+ if (v2 === void 0) continue;
1380
+ if (ROTATION_KEYS.has(key)) return parseAngleDegrees(v2);
1381
+ return typeof v2 === "number" ? v2 : void 0;
1382
+ }
1383
+ return void 0;
1384
+ }
1385
+ const v = flat[key];
1386
+ if (COLOR_KEY_SET.has(key)) {
1387
+ return typeof v === "string" || typeof v === "number" ? v : void 0;
1388
+ }
1389
+ return typeof v === "number" ? v : void 0;
1390
+ }
1391
+ function parseAngleDegrees(v) {
1392
+ if (typeof v === "number") return v;
1393
+ if (typeof v !== "string") return void 0;
1394
+ const deg = /^(-?\d*\.?\d+)deg$/.exec(v);
1395
+ if (deg) return Number(deg[1]);
1396
+ const rad = /^(-?\d*\.?\d+)rad$/.exec(v);
1397
+ if (rad) return Number(rad[1]) * 180 / Math.PI;
1398
+ return void 0;
1399
+ }
914
1400
  function collectTouchedKeys(touched, record) {
915
1401
  for (const k of ALL_KEYS) {
916
1402
  if (k in record) touched.add(k);
@@ -934,6 +1420,9 @@ function totalIterationsOf(cfg) {
934
1420
  if (r.count === "infinite") return Number.POSITIVE_INFINITY;
935
1421
  return r.count;
936
1422
  }
1423
+ function reachesTerminalPhase(cfg) {
1424
+ return Number.isFinite(totalIterationsOf(cfg));
1425
+ }
937
1426
  function targetEndValue(v) {
938
1427
  if (v === void 0) return void 0;
939
1428
  if (typeof v === "number" || typeof v === "string") return v;
@@ -990,6 +1479,15 @@ function resolveGestureLayers(gesture) {
990
1479
  if (!subState) continue;
991
1480
  const resolved = {};
992
1481
  for (const key of ALL_KEYS) {
1482
+ if (STRUCTURED_KEY_SET.has(key)) {
1483
+ if (__DEV__ && subState[key] !== void 0) {
1484
+ chunk7A6WTXNK_js.warnOnce(
1485
+ `gesture-structured-${layer}-${key}`,
1486
+ `[inertia] \`${key}\` is not supported inside \`gesture.${layer}\` and will be ignored. Drive it from \`animate\` (optionally via a variant keyed off the same state), or interpolate it yourself with \`useShadow\`.`
1487
+ );
1488
+ }
1489
+ continue;
1490
+ }
993
1491
  if (SHADOW_OFFSET_KEY_SET.has(key)) {
994
1492
  const axis = shadowOffsetAxisFor(key);
995
1493
  const so = subState.shadowOffset;
@@ -1007,7 +1505,7 @@ function resolveGestureLayers(gesture) {
1007
1505
  return out;
1008
1506
  }
1009
1507
  function useGestureLayerProgress(progress, active, declared, layer, transition, isExiting, shouldReduceMotion) {
1010
- const layerCfgSig = chunkPTRF47DA_js.stableSig(gestureLayerTransitionFor(layer, transition));
1508
+ const layerCfgSig = chunk7A6WTXNK_js.stableSig(gestureLayerTransitionFor(layer, transition));
1011
1509
  react.useEffect(() => {
1012
1510
  if (!declared) return;
1013
1511
  if (isExiting) {
@@ -1016,7 +1514,7 @@ function useGestureLayerProgress(progress, active, declared, layer, transition,
1016
1514
  }
1017
1515
  const target = active ? 1 : 0;
1018
1516
  const cfg = shouldReduceMotion ? { type: "no-animation" } : gestureLayerTransitionFor(layer, transition) ?? { type: "spring" };
1019
- progress.value = chunkPTRF47DA_js.resolveTransition(cfg, target);
1517
+ progress.value = chunk7A6WTXNK_js.resolveTransition(cfg, target);
1020
1518
  }, [active, declared, isExiting, shouldReduceMotion, layerCfgSig]);
1021
1519
  }
1022
1520
  function useGestureHandlers(gesture, rest, setPressed, setFocused, setFocusVisible, setHovered) {
@@ -1040,7 +1538,7 @@ function useGestureHandlers(gesture, rest, setPressed, setFocused, setFocusVisib
1040
1538
  if (gesture.focused || gesture.focusVisible) {
1041
1539
  handlers.onFocus = compose(rest.onFocus, () => {
1042
1540
  if (gesture.focused) setFocused(true);
1043
- if (gesture.focusVisible && chunk7AOERN53_js.isFocusVisible()) setFocusVisible(true);
1541
+ if (gesture.focusVisible && chunkWVRCKOPO_js.isFocusVisible()) setFocusVisible(true);
1044
1542
  });
1045
1543
  handlers.onBlur = compose(rest.onBlur, () => {
1046
1544
  if (gesture.focused) setFocused(false);
@@ -1081,4 +1579,6 @@ function compose(user, ours) {
1081
1579
 
1082
1580
  exports.Presence = Presence;
1083
1581
  exports.createMotionComponent = createMotionComponent;
1582
+ exports.pairBoxShadowLayers = pairBoxShadowLayers;
1583
+ exports.resolveBoxShadowInput = resolveBoxShadowInput;
1084
1584
  exports.usePresence = usePresence;