@rootnative/inertia 0.0.3 → 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.
- package/CHANGELOG.md +41 -5
- package/README.md +5 -3
- package/dist/{chunk-SGUHE5CX.mjs → chunk-4ASOELLA.mjs} +1 -1
- package/dist/{chunk-CSODMRJ7.mjs → chunk-55W7BNO2.mjs} +475 -83
- package/dist/chunk-5SRD2WCO.js +8 -0
- package/dist/{chunk-PTRF47DA.js → chunk-7A6WTXNK.js} +10 -3
- package/dist/{chunk-3XTVY34H.js → chunk-CENTULW6.js} +2 -2
- package/dist/{chunk-4PEHWDAZ.js → chunk-D5KAHWMC.js} +7 -7
- package/dist/{chunk-O22NXXCZ.mjs → chunk-J5Q46OPW.mjs} +1 -1
- package/dist/{chunk-RGNX6UZN.mjs → chunk-K3CLP74S.mjs} +2 -2
- package/dist/{chunk-BP3Y2SHQ.js → chunk-MYE5NMXW.js} +495 -101
- package/dist/{chunk-OQV66TBQ.mjs → chunk-NAOXQJ7U.mjs} +1 -1
- package/dist/{chunk-R63GIUNU.mjs → chunk-QKC3APP4.mjs} +1 -1
- package/dist/{chunk-46P57VMY.mjs → chunk-RF7J5FRM.mjs} +1 -1
- package/dist/{chunk-CY7Y64C3.mjs → chunk-TU2XFPAK.mjs} +10 -4
- package/dist/chunk-TVFNJ25Z.js +8 -0
- package/dist/chunk-VLDIFL3F.js +8 -0
- package/dist/{chunk-7AOERN53.js → chunk-WVRCKOPO.js} +3 -3
- package/dist/{chunk-W5MC3P4N.js → chunk-XMEVPEMH.js} +2 -2
- package/dist/{chunk-BQQTHG2V.mjs → chunk-YKGY22SB.mjs} +1 -1
- package/dist/gestureLayer/index.d.mts +2 -2
- package/dist/gestureLayer/index.d.ts +2 -2
- package/dist/gestureLayer/index.js +10 -10
- package/dist/gestureLayer/index.mjs +3 -3
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +48 -169
- package/dist/index.mjs +17 -137
- package/dist/motion/Image.d.mts +1 -1
- package/dist/motion/Image.d.ts +1 -1
- package/dist/motion/Image.js +5 -5
- package/dist/motion/Image.mjs +4 -4
- package/dist/motion/Pressable.d.mts +1 -1
- package/dist/motion/Pressable.d.ts +1 -1
- package/dist/motion/Pressable.js +5 -5
- package/dist/motion/Pressable.mjs +4 -4
- package/dist/motion/ScrollView.d.mts +1 -1
- package/dist/motion/ScrollView.d.ts +1 -1
- package/dist/motion/ScrollView.js +5 -5
- package/dist/motion/ScrollView.mjs +4 -4
- package/dist/motion/Text.d.mts +1 -1
- package/dist/motion/Text.d.ts +1 -1
- package/dist/motion/Text.js +5 -5
- package/dist/motion/Text.mjs +4 -4
- package/dist/motion/View.d.mts +1 -1
- package/dist/motion/View.d.ts +1 -1
- package/dist/motion/View.js +5 -5
- package/dist/motion/View.mjs +4 -4
- package/dist/touch/index.d.mts +1 -1
- package/dist/touch/index.d.ts +1 -1
- package/dist/touch/index.js +3 -3
- package/dist/touch/index.mjs +1 -1
- package/dist/{types-G1dBU2IQ.d.mts → types-37pN82yh.d.mts} +49 -14
- package/dist/{types-G1dBU2IQ.d.ts → types-37pN82yh.d.ts} +49 -14
- package/dist/{useGesture-D1e4ixJo.d.ts → useGesture-Cl4uzZIr.d.ts} +1 -1
- package/dist/{useGesture-RFY6kTL3.d.mts → useGesture-_IKkS8Dv.d.mts} +1 -1
- package/llms.txt +3 -1
- package/package.json +1 -1
- package/src/index.ts +2 -1
- package/src/internal/boxShadow.ts +177 -6
- package/src/internal/nonWorkletWarning.ts +4 -6
- package/src/internal/warnOnce.ts +28 -0
- package/src/layout/index.ts +10 -0
- package/src/layout/measureWindow.ts +135 -0
- package/src/layout/sharedRegistry.ts +107 -18
- package/src/layout/useSharedLayout.ts +256 -91
- package/src/motion/createMotionComponent.tsx +378 -39
- package/src/motion/installCheck.ts +1 -1
- package/src/transitions/index.ts +1 -1
- package/src/types.ts +52 -12
- package/src/values/useColorTransition.ts +1 -1
- package/dist/chunk-FNVFV4EY.js +0 -8
- package/dist/chunk-FWQOXA43.js +0 -8
- package/dist/chunk-KBP4LR75.js +0 -8
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useNamedTransitions, resolveNamedTransitionProp, lookupNamedTransition, useShouldReduceMotion, isFocusVisible } from './chunk-
|
|
2
|
-
import { stableSig, resolveAnimatableValue, isTopLevelTransition, resolveTransition, ensureWorkletEasing, springToReanimated, DEFAULT_SPRING } from './chunk-
|
|
1
|
+
import { useNamedTransitions, resolveNamedTransitionProp, lookupNamedTransition, useShouldReduceMotion, isFocusVisible } from './chunk-QKC3APP4.mjs';
|
|
2
|
+
import { warnOnce, stableSig, resolveAnimatableValue, isTopLevelTransition, resolveTransition, ensureWorkletEasing, springToReanimated, DEFAULT_SPRING } from './chunk-TU2XFPAK.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, cancelAnimation, useAnimatedStyle, interpolateColor, reanimatedVersion, runOnJS, LinearTransition, withSequence, withTiming, withSpring } from 'react-native-reanimated';
|
|
@@ -129,6 +129,175 @@ function PresenceItem({
|
|
|
129
129
|
);
|
|
130
130
|
return /* @__PURE__ */ jsx(PresenceContext.Provider, { value, children });
|
|
131
131
|
}
|
|
132
|
+
|
|
133
|
+
// src/internal/boxShadow.ts
|
|
134
|
+
var LENGTH = /^[+-]?(\d+\.?\d*|\.\d+)(px)?$/i;
|
|
135
|
+
var UNIT_LIKE = /^[+-]?(\d+\.?\d*|\.\d+)[a-z%]+$/i;
|
|
136
|
+
function invalid(input, reason) {
|
|
137
|
+
return new Error(
|
|
138
|
+
`[inertia] parseBoxShadow: ${reason} in ${JSON.stringify(input)}. Expected CSS box-shadow syntax with px lengths: '[inset] <offset-x> <offset-y> [blur] [spread] [color], ...'`
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
function splitLayers(input) {
|
|
142
|
+
const layers = [];
|
|
143
|
+
let depth = 0;
|
|
144
|
+
let start = 0;
|
|
145
|
+
for (let i = 0; i < input.length; i++) {
|
|
146
|
+
const ch = input[i];
|
|
147
|
+
if (ch === "(") depth++;
|
|
148
|
+
else if (ch === ")") depth--;
|
|
149
|
+
else if (ch === "," && depth === 0) {
|
|
150
|
+
layers.push(input.slice(start, i));
|
|
151
|
+
start = i + 1;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
layers.push(input.slice(start));
|
|
155
|
+
return layers;
|
|
156
|
+
}
|
|
157
|
+
function tokenize(layer) {
|
|
158
|
+
const tokens = [];
|
|
159
|
+
let depth = 0;
|
|
160
|
+
let current = "";
|
|
161
|
+
for (const ch of layer) {
|
|
162
|
+
if (ch === "(") depth++;
|
|
163
|
+
else if (ch === ")") depth--;
|
|
164
|
+
if (depth === 0 && /\s/.test(ch)) {
|
|
165
|
+
if (current) tokens.push(current);
|
|
166
|
+
current = "";
|
|
167
|
+
} else {
|
|
168
|
+
current += ch;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
if (current) tokens.push(current);
|
|
172
|
+
return tokens;
|
|
173
|
+
}
|
|
174
|
+
function parseBoxShadow(input) {
|
|
175
|
+
const trimmed = input.trim();
|
|
176
|
+
if (trimmed === "") throw invalid(input, "empty string");
|
|
177
|
+
if (trimmed.toLowerCase() === "none") return [];
|
|
178
|
+
return splitLayers(trimmed).map((layerString) => {
|
|
179
|
+
const tokens = tokenize(layerString.trim());
|
|
180
|
+
if (tokens.length === 0) throw invalid(input, "empty layer");
|
|
181
|
+
const lengths = [];
|
|
182
|
+
let color;
|
|
183
|
+
let inset = false;
|
|
184
|
+
for (const token of tokens) {
|
|
185
|
+
if (token.toLowerCase() === "inset") {
|
|
186
|
+
if (inset) throw invalid(input, "duplicate 'inset'");
|
|
187
|
+
inset = true;
|
|
188
|
+
} else if (LENGTH.test(token)) {
|
|
189
|
+
lengths.push(parseFloat(token));
|
|
190
|
+
} else if (UNIT_LIKE.test(token)) {
|
|
191
|
+
throw invalid(input, `unsupported unit in ${JSON.stringify(token)}`);
|
|
192
|
+
} else {
|
|
193
|
+
if (color !== void 0) throw invalid(input, "multiple colors");
|
|
194
|
+
color = token;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
if (lengths.length < 2 || lengths.length > 4) {
|
|
198
|
+
throw invalid(input, `expected 2-4 lengths, got ${lengths.length}`);
|
|
199
|
+
}
|
|
200
|
+
const [offsetX = 0, offsetY = 0, blurRadius = 0, spreadDistance = 0] = lengths;
|
|
201
|
+
if (blurRadius < 0) throw invalid(input, "negative blur radius");
|
|
202
|
+
return {
|
|
203
|
+
offsetX,
|
|
204
|
+
offsetY,
|
|
205
|
+
blurRadius,
|
|
206
|
+
spreadDistance,
|
|
207
|
+
color: color ?? "black",
|
|
208
|
+
inset
|
|
209
|
+
};
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
function resolveBoxShadowInput(input) {
|
|
213
|
+
if (input === void 0) return [];
|
|
214
|
+
if (typeof input === "string") return parseBoxShadow(input);
|
|
215
|
+
return input.map((layer) => ({
|
|
216
|
+
offsetX: coerceLength(layer.offsetX, "offsetX"),
|
|
217
|
+
offsetY: coerceLength(layer.offsetY, "offsetY"),
|
|
218
|
+
blurRadius: coerceLength(layer.blurRadius, "blurRadius"),
|
|
219
|
+
spreadDistance: coerceLength(layer.spreadDistance, "spreadDistance"),
|
|
220
|
+
color: layer.color ?? "black",
|
|
221
|
+
inset: layer.inset ?? false
|
|
222
|
+
}));
|
|
223
|
+
}
|
|
224
|
+
function pairBoxShadowLayers(from, to) {
|
|
225
|
+
const count = Math.max(from.length, to.length);
|
|
226
|
+
const pairs = [];
|
|
227
|
+
for (let i = 0; i < count; i++) {
|
|
228
|
+
const a = from[i];
|
|
229
|
+
const b = to[i];
|
|
230
|
+
const fromLayer = a ?? invisibleLayer(b.inset);
|
|
231
|
+
const toLayer = b ?? invisibleLayer(a.inset);
|
|
232
|
+
if (fromLayer.inset !== toLayer.inset) {
|
|
233
|
+
throw new Error(
|
|
234
|
+
`[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).`
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
pairs.push({ from: fromLayer, to: toLayer });
|
|
238
|
+
}
|
|
239
|
+
return pairs;
|
|
240
|
+
}
|
|
241
|
+
function invisibleLayer(inset) {
|
|
242
|
+
return {
|
|
243
|
+
offsetX: 0,
|
|
244
|
+
offsetY: 0,
|
|
245
|
+
blurRadius: 0,
|
|
246
|
+
spreadDistance: 0,
|
|
247
|
+
color: "transparent",
|
|
248
|
+
inset
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
function coerceLength(value, field) {
|
|
252
|
+
if (value === void 0) return 0;
|
|
253
|
+
if (typeof value === "number") return value;
|
|
254
|
+
const trimmed = typeof value === "string" ? value.trim() : "";
|
|
255
|
+
if (!LENGTH.test(trimmed)) {
|
|
256
|
+
throw new Error(
|
|
257
|
+
`[inertia] boxShadow: ${field} must be a number or a px length, got ${JSON.stringify(value)}.`
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
return parseFloat(trimmed);
|
|
261
|
+
}
|
|
262
|
+
function strip(layer) {
|
|
263
|
+
const { inset: _inset, ...rest } = layer;
|
|
264
|
+
return rest;
|
|
265
|
+
}
|
|
266
|
+
function markInset(insets, i, count) {
|
|
267
|
+
const list = insets ?? new Array(count).fill(false);
|
|
268
|
+
list[i] = true;
|
|
269
|
+
return list;
|
|
270
|
+
}
|
|
271
|
+
function normalizeBoxShadow(input) {
|
|
272
|
+
const resolved = resolveBoxShadowInput(input);
|
|
273
|
+
const layers = [];
|
|
274
|
+
let insets = null;
|
|
275
|
+
for (let i = 0; i < resolved.length; i++) {
|
|
276
|
+
const layer = resolved[i];
|
|
277
|
+
layers.push(strip(layer));
|
|
278
|
+
if (layer.inset) insets = markInset(insets, i, resolved.length);
|
|
279
|
+
}
|
|
280
|
+
return { layers, insets };
|
|
281
|
+
}
|
|
282
|
+
function prepareBoxShadowAnimation(current, target) {
|
|
283
|
+
const pairs = pairBoxShadowLayers(
|
|
284
|
+
current.layers.map((layer, i) => ({
|
|
285
|
+
...layer,
|
|
286
|
+
inset: current.insets?.[i] ?? false
|
|
287
|
+
})),
|
|
288
|
+
resolveBoxShadowInput(target)
|
|
289
|
+
);
|
|
290
|
+
const from = [];
|
|
291
|
+
const to = [];
|
|
292
|
+
let insets = null;
|
|
293
|
+
for (let i = 0; i < pairs.length; i++) {
|
|
294
|
+
const pair = pairs[i];
|
|
295
|
+
from.push(strip(pair.from));
|
|
296
|
+
to.push(strip(pair.to));
|
|
297
|
+
if (pair.to.inset) insets = markInset(insets, i, pairs.length);
|
|
298
|
+
}
|
|
299
|
+
return { from, to, insets };
|
|
300
|
+
}
|
|
132
301
|
function resolveLayoutTransition(layout) {
|
|
133
302
|
if (!layout) return void 0;
|
|
134
303
|
const cfg = layout === true ? { type: "spring" } : layout;
|
|
@@ -162,72 +331,138 @@ function sweepExpired(at) {
|
|
|
162
331
|
if (entry.expiresAt < at) REGISTRY.delete(id);
|
|
163
332
|
}
|
|
164
333
|
}
|
|
165
|
-
function registerLayout(id, rect) {
|
|
334
|
+
function registerLayout(id, rect, remeasure, readStyles) {
|
|
166
335
|
const at = now();
|
|
167
336
|
sweepExpired(at);
|
|
168
|
-
REGISTRY.set(id, {
|
|
337
|
+
REGISTRY.set(id, {
|
|
338
|
+
rect,
|
|
339
|
+
expiresAt: at + SHARED_LAYOUT_TTL_MS,
|
|
340
|
+
remeasure,
|
|
341
|
+
readStyles
|
|
342
|
+
});
|
|
169
343
|
}
|
|
170
|
-
function releaseLayout(id, rect) {
|
|
344
|
+
function releaseLayout(id, rect, styles) {
|
|
171
345
|
const at = now();
|
|
172
346
|
sweepExpired(at);
|
|
173
|
-
REGISTRY.set(id, { rect, expiresAt: at + SHARED_LAYOUT_TTL_MS });
|
|
347
|
+
REGISTRY.set(id, { rect, expiresAt: at + SHARED_LAYOUT_TTL_MS, styles });
|
|
174
348
|
}
|
|
175
349
|
function consumeLayout(id) {
|
|
176
350
|
const entry = REGISTRY.get(id);
|
|
177
351
|
if (!entry) return void 0;
|
|
178
352
|
REGISTRY.delete(id);
|
|
179
353
|
if (entry.expiresAt < now()) return void 0;
|
|
180
|
-
return
|
|
354
|
+
return {
|
|
355
|
+
rect: entry.rect,
|
|
356
|
+
remeasure: entry.remeasure,
|
|
357
|
+
styles: entry.styles,
|
|
358
|
+
readStyles: entry.readStyles
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// src/layout/measureWindow.ts
|
|
363
|
+
var defaultMeasurer = (node) => {
|
|
364
|
+
const measure = node?.measureInWindow;
|
|
365
|
+
if (typeof measure !== "function") return void 0;
|
|
366
|
+
let result;
|
|
367
|
+
let returned = false;
|
|
368
|
+
try {
|
|
369
|
+
measure.call(node, (x, y, width, height) => {
|
|
370
|
+
if (returned) return;
|
|
371
|
+
result = { x, y, width, height };
|
|
372
|
+
});
|
|
373
|
+
} catch {
|
|
374
|
+
returned = true;
|
|
375
|
+
return void 0;
|
|
376
|
+
}
|
|
377
|
+
returned = true;
|
|
378
|
+
return result;
|
|
379
|
+
};
|
|
380
|
+
var measurer = defaultMeasurer;
|
|
381
|
+
function usable(rect) {
|
|
382
|
+
const { x, y, width, height } = rect;
|
|
383
|
+
for (const v of [x, y, width, height]) {
|
|
384
|
+
if (typeof v !== "number" || !Number.isFinite(v)) return false;
|
|
385
|
+
}
|
|
386
|
+
return width !== 0 || height !== 0;
|
|
387
|
+
}
|
|
388
|
+
function measureWindowRect(node) {
|
|
389
|
+
const measured = measurer(node);
|
|
390
|
+
if (!measured || !usable(measured)) return void 0;
|
|
391
|
+
return toSharedRect(measured, "window");
|
|
392
|
+
}
|
|
393
|
+
function toSharedRect(rect, space) {
|
|
394
|
+
return { ...rect, space };
|
|
181
395
|
}
|
|
182
396
|
function useSharedLayout(options) {
|
|
183
|
-
const {
|
|
397
|
+
const {
|
|
398
|
+
layoutId,
|
|
399
|
+
userRef,
|
|
400
|
+
transition,
|
|
401
|
+
shouldReduceMotion,
|
|
402
|
+
userOnLayout,
|
|
403
|
+
readStyles
|
|
404
|
+
} = options;
|
|
184
405
|
const dx = useSharedValue(0);
|
|
185
406
|
const dy = useSharedValue(0);
|
|
186
407
|
const sx = useSharedValue(1);
|
|
187
408
|
const sy = useSharedValue(1);
|
|
409
|
+
const snapshot = useSharedValue(null);
|
|
410
|
+
const carryProgress = useSharedValue(0);
|
|
188
411
|
const lastRectRef = useRef(null);
|
|
189
412
|
const consumedRef = useRef(false);
|
|
413
|
+
const nodeRef = useRef(null);
|
|
190
414
|
const transitionRef = useRef(transition);
|
|
191
415
|
transitionRef.current = transition;
|
|
192
416
|
const reducedMotionRef = useRef(shouldReduceMotion);
|
|
193
417
|
reducedMotionRef.current = shouldReduceMotion;
|
|
418
|
+
const readStylesRef = useRef(readStyles);
|
|
419
|
+
readStylesRef.current = readStyles;
|
|
194
420
|
const setRef = useCallback(
|
|
195
421
|
(node) => {
|
|
422
|
+
nodeRef.current = node;
|
|
196
423
|
if (typeof userRef === "function") userRef(node);
|
|
197
424
|
else if (userRef) userRef.current = node;
|
|
198
425
|
},
|
|
199
426
|
[userRef]
|
|
200
427
|
);
|
|
428
|
+
const remeasure = useCallback(() => measureWindowRect(nodeRef.current), []);
|
|
429
|
+
const snapshotStyles = useCallback(() => readStylesRef.current?.(), []);
|
|
430
|
+
const startTransition = useCallback(
|
|
431
|
+
(source, sourceRect, target) => {
|
|
432
|
+
if (sourceRect.space !== target.space) return;
|
|
433
|
+
const shared = {
|
|
434
|
+
transition: transitionRef.current,
|
|
435
|
+
shouldReduceMotion: reducedMotionRef.current
|
|
436
|
+
};
|
|
437
|
+
applyFlip({ source: sourceRect, target, dx, dy, sx, sy, ...shared });
|
|
438
|
+
applyStyleCarry({
|
|
439
|
+
snapshot,
|
|
440
|
+
progress: carryProgress,
|
|
441
|
+
// Prefer a live read for the same reason the rect is re-measured: a
|
|
442
|
+
// still-mounted source may have moved on since its last layout.
|
|
443
|
+
styles: source.readStyles?.() ?? source.styles,
|
|
444
|
+
...shared
|
|
445
|
+
});
|
|
446
|
+
},
|
|
447
|
+
[dx, dy, sx, sy, snapshot, carryProgress]
|
|
448
|
+
);
|
|
201
449
|
const onLayout = useCallback(
|
|
202
450
|
(event) => {
|
|
203
451
|
userOnLayout?.(event);
|
|
204
452
|
if (!layoutId) return;
|
|
205
453
|
const { x, y, width, height } = event.nativeEvent.layout;
|
|
206
|
-
const rect = { x, y, width, height };
|
|
207
|
-
lastRectRef.current = rect;
|
|
208
454
|
let source;
|
|
209
455
|
if (!consumedRef.current) {
|
|
210
456
|
consumedRef.current = true;
|
|
211
457
|
source = consumeLayout(layoutId);
|
|
212
458
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
dx,
|
|
219
|
-
dy,
|
|
220
|
-
sx,
|
|
221
|
-
sy,
|
|
222
|
-
transition: transitionRef.current,
|
|
223
|
-
shouldReduceMotion: reducedMotionRef.current
|
|
224
|
-
});
|
|
225
|
-
}
|
|
459
|
+
const rect = measureWindowRect(nodeRef.current) ?? { x, y, width, height, space: "parent" };
|
|
460
|
+
lastRectRef.current = rect;
|
|
461
|
+
registerLayout(layoutId, rect, remeasure, snapshotStyles);
|
|
462
|
+
if (!source) return;
|
|
463
|
+
startTransition(source, source.remeasure?.() ?? source.rect, rect);
|
|
226
464
|
},
|
|
227
|
-
|
|
228
|
-
// exhaustive-deps would flag them — including them is harmless and
|
|
229
|
-
// silences the warning.
|
|
230
|
-
[layoutId, userOnLayout, dx, dy, sx, sy]
|
|
465
|
+
[layoutId, userOnLayout, remeasure, snapshotStyles, startTransition]
|
|
231
466
|
);
|
|
232
467
|
useEffect(() => {
|
|
233
468
|
consumedRef.current = false;
|
|
@@ -237,18 +472,49 @@ function useSharedLayout(options) {
|
|
|
237
472
|
if (!layoutId) return;
|
|
238
473
|
const rect = lastRectRef.current;
|
|
239
474
|
if (!rect) return;
|
|
240
|
-
releaseLayout(layoutId, rect);
|
|
475
|
+
releaseLayout(layoutId, rect, snapshotStyles());
|
|
241
476
|
};
|
|
242
|
-
}, [layoutId]);
|
|
477
|
+
}, [layoutId, snapshotStyles]);
|
|
478
|
+
useEffect(
|
|
479
|
+
() => () => {
|
|
480
|
+
cancelAnimation(dx);
|
|
481
|
+
cancelAnimation(dy);
|
|
482
|
+
cancelAnimation(sx);
|
|
483
|
+
cancelAnimation(sy);
|
|
484
|
+
cancelAnimation(carryProgress);
|
|
485
|
+
},
|
|
486
|
+
// The FLIP shared values are identity-stable per hook instance.
|
|
487
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
488
|
+
[]
|
|
489
|
+
);
|
|
243
490
|
return useMemo(
|
|
244
491
|
() => ({
|
|
245
492
|
flip: { dx, dy, sx, sy },
|
|
493
|
+
carry: { snapshot, progress: carryProgress },
|
|
246
494
|
setRef,
|
|
247
495
|
onLayout
|
|
248
496
|
}),
|
|
249
|
-
[dx, dy, sx, sy, setRef, onLayout]
|
|
497
|
+
[dx, dy, sx, sy, snapshot, carryProgress, setRef, onLayout]
|
|
250
498
|
);
|
|
251
499
|
}
|
|
500
|
+
function legBuilder(transition) {
|
|
501
|
+
if (transition?.type === "timing") {
|
|
502
|
+
const duration = transition.duration ?? 300;
|
|
503
|
+
return (from, to) => withSequence(
|
|
504
|
+
withTiming(from, { duration: 0 }),
|
|
505
|
+
withTiming(to, { duration })
|
|
506
|
+
);
|
|
507
|
+
}
|
|
508
|
+
const springCfg = transition?.type === "spring" ? { ...DEFAULT_SPRING, ...transition } : { type: "spring", ...DEFAULT_SPRING };
|
|
509
|
+
const springParams = springToReanimated(springCfg);
|
|
510
|
+
return (from, to) => withSequence(
|
|
511
|
+
withTiming(from, { duration: 0 }),
|
|
512
|
+
withSpring(to, springParams)
|
|
513
|
+
);
|
|
514
|
+
}
|
|
515
|
+
function shouldSnap(transition, shouldReduceMotion) {
|
|
516
|
+
return shouldReduceMotion || transition?.type === "no-animation";
|
|
517
|
+
}
|
|
252
518
|
function applyFlip(args) {
|
|
253
519
|
const { source, target, dx, dy, sx, sy, transition, shouldReduceMotion } = args;
|
|
254
520
|
const sourceCenterX = source.x + source.width / 2;
|
|
@@ -259,58 +525,29 @@ function applyFlip(args) {
|
|
|
259
525
|
const deltaY = sourceCenterY - targetCenterY;
|
|
260
526
|
const scaleX = target.width > 0 ? source.width / target.width : 1;
|
|
261
527
|
const scaleY = target.height > 0 ? source.height / target.height : 1;
|
|
262
|
-
if (shouldReduceMotion) {
|
|
263
|
-
dx.value = 0;
|
|
264
|
-
dy.value = 0;
|
|
265
|
-
sx.value = 1;
|
|
266
|
-
sy.value = 1;
|
|
267
|
-
return;
|
|
268
|
-
}
|
|
269
|
-
if (transition?.type === "no-animation") {
|
|
528
|
+
if (shouldSnap(transition, shouldReduceMotion)) {
|
|
270
529
|
dx.value = 0;
|
|
271
530
|
dy.value = 0;
|
|
272
531
|
sx.value = 1;
|
|
273
532
|
sy.value = 1;
|
|
274
533
|
return;
|
|
275
534
|
}
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
withTiming(1, { duration })
|
|
289
|
-
);
|
|
290
|
-
sy.value = withSequence(
|
|
291
|
-
withTiming(scaleY, { duration: 0 }),
|
|
292
|
-
withTiming(1, { duration })
|
|
293
|
-
);
|
|
535
|
+
const leg = legBuilder(transition);
|
|
536
|
+
dx.value = leg(deltaX, 0);
|
|
537
|
+
dy.value = leg(deltaY, 0);
|
|
538
|
+
sx.value = leg(scaleX, 1);
|
|
539
|
+
sy.value = leg(scaleY, 1);
|
|
540
|
+
}
|
|
541
|
+
function applyStyleCarry(args) {
|
|
542
|
+
const { snapshot, progress, styles, transition, shouldReduceMotion } = args;
|
|
543
|
+
if (!styles) return;
|
|
544
|
+
if (shouldSnap(transition, shouldReduceMotion)) {
|
|
545
|
+
snapshot.value = null;
|
|
546
|
+
progress.value = 0;
|
|
294
547
|
return;
|
|
295
548
|
}
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
dx.value = withSequence(
|
|
299
|
-
withTiming(deltaX, { duration: 0 }),
|
|
300
|
-
withSpring(0, springParams)
|
|
301
|
-
);
|
|
302
|
-
dy.value = withSequence(
|
|
303
|
-
withTiming(deltaY, { duration: 0 }),
|
|
304
|
-
withSpring(0, springParams)
|
|
305
|
-
);
|
|
306
|
-
sx.value = withSequence(
|
|
307
|
-
withTiming(scaleX, { duration: 0 }),
|
|
308
|
-
withSpring(1, springParams)
|
|
309
|
-
);
|
|
310
|
-
sy.value = withSequence(
|
|
311
|
-
withTiming(scaleY, { duration: 0 }),
|
|
312
|
-
withSpring(1, springParams)
|
|
313
|
-
);
|
|
549
|
+
snapshot.value = styles;
|
|
550
|
+
progress.value = legBuilder(transition)(1, 0);
|
|
314
551
|
}
|
|
315
552
|
var alreadyChecked = false;
|
|
316
553
|
function ensureReanimatedInstalled() {
|
|
@@ -324,7 +561,7 @@ function ensureReanimatedInstalled() {
|
|
|
324
561
|
const major = parseInt(version.split(".")[0] ?? "0", 10);
|
|
325
562
|
if (major < 4) {
|
|
326
563
|
console.error(
|
|
327
|
-
`[inertia] react-native-reanimated
|
|
564
|
+
`[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).`
|
|
328
565
|
);
|
|
329
566
|
return;
|
|
330
567
|
}
|
|
@@ -367,15 +604,28 @@ var COLOR_KEYS = [
|
|
|
367
604
|
"shadowColor"
|
|
368
605
|
];
|
|
369
606
|
var SHADOW_OFFSET_KEYS = ["shadowOffsetWidth", "shadowOffsetHeight"];
|
|
607
|
+
var STRUCTURED_KEYS = ["boxShadow"];
|
|
608
|
+
var SHARED_STYLE_KEYS = [
|
|
609
|
+
"opacity",
|
|
610
|
+
"borderRadius",
|
|
611
|
+
"backgroundColor",
|
|
612
|
+
"borderColor",
|
|
613
|
+
"color",
|
|
614
|
+
"tintColor"
|
|
615
|
+
];
|
|
370
616
|
var ALL_KEYS = [
|
|
371
617
|
...TRANSFORM_KEYS,
|
|
372
618
|
...NUMERIC_TOP_LEVEL_KEYS,
|
|
373
619
|
...COLOR_KEYS,
|
|
374
|
-
...SHADOW_OFFSET_KEYS
|
|
620
|
+
...SHADOW_OFFSET_KEYS,
|
|
621
|
+
...STRUCTURED_KEYS
|
|
375
622
|
];
|
|
376
623
|
var TRANSFORM_KEY_SET = new Set(TRANSFORM_KEYS);
|
|
377
624
|
var COLOR_KEY_SET = new Set(COLOR_KEYS);
|
|
378
625
|
var SHADOW_OFFSET_KEY_SET = new Set(SHADOW_OFFSET_KEYS);
|
|
626
|
+
var STRUCTURED_KEY_SET = new Set(STRUCTURED_KEYS);
|
|
627
|
+
var SHARED_STYLE_KEY_SET = new Set(SHARED_STYLE_KEYS);
|
|
628
|
+
var NO_BOX_SHADOW = Object.freeze([]);
|
|
379
629
|
var GESTURE_LAYER_NAMES = [
|
|
380
630
|
"hovered",
|
|
381
631
|
"focused",
|
|
@@ -410,7 +660,8 @@ var DEFAULT_RESTING = {
|
|
|
410
660
|
tintColor: "transparent",
|
|
411
661
|
shadowColor: "transparent",
|
|
412
662
|
shadowOffsetWidth: 0,
|
|
413
|
-
shadowOffsetHeight: 0
|
|
663
|
+
shadowOffsetHeight: 0,
|
|
664
|
+
boxShadow: NO_BOX_SHADOW
|
|
414
665
|
};
|
|
415
666
|
function transitionFor(prop, transition) {
|
|
416
667
|
if (!transition) return void 0;
|
|
@@ -501,6 +752,16 @@ function createMotionComponent(Component) {
|
|
|
501
752
|
const [focused, setFocused] = useState(false);
|
|
502
753
|
const [focusVisible, setFocusVisible] = useState(false);
|
|
503
754
|
const [hovered, setHovered] = useState(false);
|
|
755
|
+
const hasLayoutId = layoutId !== void 0;
|
|
756
|
+
let flatStyle;
|
|
757
|
+
let flatStyleRead = false;
|
|
758
|
+
const getFlatStyle = () => {
|
|
759
|
+
if (!flatStyleRead) {
|
|
760
|
+
flatStyleRead = true;
|
|
761
|
+
flatStyle = StyleSheet.flatten(style);
|
|
762
|
+
}
|
|
763
|
+
return flatStyle;
|
|
764
|
+
};
|
|
504
765
|
const touched = /* @__PURE__ */ new Set();
|
|
505
766
|
collectTouchedKeys(touched, animateRecord);
|
|
506
767
|
if (initialRecord) collectTouchedKeys(touched, initialRecord);
|
|
@@ -522,9 +783,19 @@ function createMotionComponent(Component) {
|
|
|
522
783
|
}
|
|
523
784
|
}
|
|
524
785
|
if (exitRecord) collectTouchedKeys(touched, exitRecord);
|
|
786
|
+
if (hasLayoutId) {
|
|
787
|
+
const flat = getFlatStyle();
|
|
788
|
+
if (flat) {
|
|
789
|
+
for (const key of SHARED_STYLE_KEYS) {
|
|
790
|
+
if (touched.has(key)) continue;
|
|
791
|
+
if (styleValueFor(flat, key) !== void 0) touched.add(key);
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
}
|
|
525
795
|
const activeKeysRef = useRef(null);
|
|
526
796
|
const hasTransformRef = useRef(false);
|
|
527
797
|
const hasShadowOffsetRef = useRef(false);
|
|
798
|
+
const hasBoxShadowRef = useRef(false);
|
|
528
799
|
const prevActive = activeKeysRef.current;
|
|
529
800
|
let grew = prevActive === null;
|
|
530
801
|
if (!grew && prevActive) {
|
|
@@ -545,6 +816,15 @@ function createMotionComponent(Component) {
|
|
|
545
816
|
hasShadowOffsetRef.current = activeKeysRef.current.some(
|
|
546
817
|
(k) => SHADOW_OFFSET_KEY_SET.has(k)
|
|
547
818
|
);
|
|
819
|
+
hasBoxShadowRef.current = activeKeysRef.current.includes("boxShadow");
|
|
820
|
+
if (__DEV__ && hasBoxShadowRef.current && activeKeysRef.current.some(
|
|
821
|
+
(k) => k !== "boxShadow" && k.startsWith("shadow")
|
|
822
|
+
)) {
|
|
823
|
+
warnOnce(
|
|
824
|
+
"boxShadow-with-native-shadow",
|
|
825
|
+
"[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."
|
|
826
|
+
);
|
|
827
|
+
}
|
|
548
828
|
}
|
|
549
829
|
const drivenNow = /* @__PURE__ */ new Set();
|
|
550
830
|
collectTouchedKeys(drivenNow, animateRecord);
|
|
@@ -555,17 +835,35 @@ function createMotionComponent(Component) {
|
|
|
555
835
|
const activeKeys = activeKeysRef.current;
|
|
556
836
|
const everDriven = everDrivenRef.current;
|
|
557
837
|
const styleResting = {};
|
|
838
|
+
let styleRestingShadow = null;
|
|
558
839
|
if (activeKeys.some((k) => !everDriven.has(k))) {
|
|
559
|
-
const flat =
|
|
840
|
+
const flat = getFlatStyle();
|
|
560
841
|
if (flat) {
|
|
561
842
|
for (const key of activeKeys) {
|
|
562
843
|
if (everDriven.has(key)) continue;
|
|
844
|
+
if (key === "boxShadow") {
|
|
845
|
+
const raw = flat.boxShadow;
|
|
846
|
+
if (raw !== void 0) {
|
|
847
|
+
styleRestingShadow = normalizeBoxShadow(raw);
|
|
848
|
+
styleResting.boxShadow = styleRestingShadow.layers;
|
|
849
|
+
}
|
|
850
|
+
continue;
|
|
851
|
+
}
|
|
563
852
|
const v = styleValueFor(flat, key);
|
|
564
853
|
if (v !== void 0) styleResting[key] = v;
|
|
565
854
|
}
|
|
566
855
|
}
|
|
567
856
|
}
|
|
857
|
+
const boxShadowSeedRef = useRef(null);
|
|
858
|
+
if (boxShadowSeedRef.current === null) {
|
|
859
|
+
const source = initial === false ? animateRecord.boxShadow : initialRecord?.boxShadow ?? animateRecord.boxShadow;
|
|
860
|
+
boxShadowSeedRef.current = source !== void 0 ? normalizeBoxShadow(source) : styleRestingShadow ?? {
|
|
861
|
+
layers: [...NO_BOX_SHADOW],
|
|
862
|
+
insets: null
|
|
863
|
+
};
|
|
864
|
+
}
|
|
568
865
|
const sharedValues = useAnimatableSharedValues((key) => {
|
|
866
|
+
if (key === "boxShadow") return boxShadowSeedRef.current.layers;
|
|
569
867
|
if (SHADOW_OFFSET_KEY_SET.has(key)) {
|
|
570
868
|
const axis = shadowOffsetAxisFor(key);
|
|
571
869
|
if (initial === false) {
|
|
@@ -582,11 +880,17 @@ function createMotionComponent(Component) {
|
|
|
582
880
|
}
|
|
583
881
|
return initialRecord?.[key] ?? restValue(animateRecord[key]) ?? styleResting[key] ?? DEFAULT_RESTING[key];
|
|
584
882
|
});
|
|
883
|
+
const boxShadowInsets = useSharedValue(
|
|
884
|
+
boxShadowSeedRef.current.insets
|
|
885
|
+
);
|
|
585
886
|
const styleRestingSig = stableSig(styleResting);
|
|
586
887
|
useEffect(() => {
|
|
587
888
|
for (const key of activeKeysRef.current) {
|
|
588
889
|
if (everDrivenRef.current.has(key)) continue;
|
|
589
890
|
sharedValues[key].value = styleResting[key] ?? DEFAULT_RESTING[key];
|
|
891
|
+
if (key === "boxShadow") {
|
|
892
|
+
boxShadowInsets.value = styleRestingShadow?.insets ?? null;
|
|
893
|
+
}
|
|
590
894
|
}
|
|
591
895
|
}, [styleRestingSig]);
|
|
592
896
|
const pressedProgress = useSharedValue(0);
|
|
@@ -643,6 +947,30 @@ function createMotionComponent(Component) {
|
|
|
643
947
|
}
|
|
644
948
|
const transformGroup = transformPending > 0 ? { remaining: transformPending } : void 0;
|
|
645
949
|
for (const key of ALL_KEYS) {
|
|
950
|
+
if (key === "boxShadow") {
|
|
951
|
+
const shadowTarget = baseRecord.boxShadow;
|
|
952
|
+
if (shadowTarget === void 0) continue;
|
|
953
|
+
const cfg2 = configFor("boxShadow");
|
|
954
|
+
if (isExiting && reachesTerminalPhase(cfg2)) pending++;
|
|
955
|
+
driveBoxShadow(
|
|
956
|
+
sharedValues.boxShadow,
|
|
957
|
+
boxShadowInsets,
|
|
958
|
+
shadowTarget,
|
|
959
|
+
cfg2,
|
|
960
|
+
makeKeyCallbackFactory(
|
|
961
|
+
"boxShadow",
|
|
962
|
+
sharedValues.boxShadow,
|
|
963
|
+
// The declared target, not the padded one — the padding is an
|
|
964
|
+
// implementation detail of getting Reanimated to interpolate.
|
|
965
|
+
shadowTarget,
|
|
966
|
+
onAnimationEndRef,
|
|
967
|
+
{ stepCount: 1, totalIterations: totalIterationsOf(cfg2) },
|
|
968
|
+
isExiting ? onSettle : void 0,
|
|
969
|
+
void 0
|
|
970
|
+
)
|
|
971
|
+
);
|
|
972
|
+
continue;
|
|
973
|
+
}
|
|
646
974
|
const target = SHADOW_OFFSET_KEY_SET.has(key) ? shadowOffsetAxisValue(
|
|
647
975
|
baseRecord.shadowOffset,
|
|
648
976
|
shadowOffsetAxisFor(key)
|
|
@@ -708,19 +1036,34 @@ function createMotionComponent(Component) {
|
|
|
708
1036
|
isExiting,
|
|
709
1037
|
shouldReduceMotion
|
|
710
1038
|
);
|
|
1039
|
+
const readSharedStyles = () => {
|
|
1040
|
+
if (!hasLayoutId) return void 0;
|
|
1041
|
+
const out = {};
|
|
1042
|
+
let any = false;
|
|
1043
|
+
for (const key of activeKeysRef.current) {
|
|
1044
|
+
if (!SHARED_STYLE_KEY_SET.has(key)) continue;
|
|
1045
|
+
const v = sharedValues[key].value;
|
|
1046
|
+
if (typeof v !== "number" && typeof v !== "string") continue;
|
|
1047
|
+
out[key] = v;
|
|
1048
|
+
any = true;
|
|
1049
|
+
}
|
|
1050
|
+
return any ? out : void 0;
|
|
1051
|
+
};
|
|
711
1052
|
const sharedLayout = useSharedLayout({
|
|
712
1053
|
layoutId,
|
|
713
1054
|
userRef: ref,
|
|
714
1055
|
transition: isTopLevelTransition(transition) ? transition : void 0,
|
|
715
1056
|
shouldReduceMotion,
|
|
716
|
-
userOnLayout
|
|
1057
|
+
userOnLayout,
|
|
1058
|
+
readStyles: readSharedStyles
|
|
717
1059
|
});
|
|
718
1060
|
const flip = sharedLayout.flip;
|
|
719
|
-
const
|
|
1061
|
+
const carry = sharedLayout.carry;
|
|
720
1062
|
const animatedStyle = useAnimatedStyle(() => {
|
|
721
1063
|
const activeKeys2 = activeKeysRef.current;
|
|
722
1064
|
const hasTransform = hasTransformRef.current;
|
|
723
1065
|
const hasShadowOffset = hasShadowOffsetRef.current;
|
|
1066
|
+
const hasBoxShadow = hasBoxShadowRef.current;
|
|
724
1067
|
const out = {};
|
|
725
1068
|
const transform = [];
|
|
726
1069
|
let shadowOffsetW = 0;
|
|
@@ -729,12 +1072,15 @@ function createMotionComponent(Component) {
|
|
|
729
1072
|
const pf = focusedProgress.value;
|
|
730
1073
|
const pfv = focusVisibleProgress.value;
|
|
731
1074
|
const pp = pressedProgress.value;
|
|
1075
|
+
const carried = carry.snapshot.value;
|
|
1076
|
+
const pc = carry.progress.value;
|
|
732
1077
|
const layers = gestureSV.value;
|
|
733
1078
|
const hoveredLayer = layers ? layers.hovered : null;
|
|
734
1079
|
const focusedLayer = layers ? layers.focused : null;
|
|
735
1080
|
const focusVisibleLayer = layers ? layers.focusVisible : null;
|
|
736
1081
|
const pressedLayer = layers ? layers.pressed : null;
|
|
737
1082
|
for (const key of activeKeys2) {
|
|
1083
|
+
if (key === "boxShadow") continue;
|
|
738
1084
|
let v = sharedValues[key].value;
|
|
739
1085
|
const isColor = COLOR_KEY_SET.has(key);
|
|
740
1086
|
if (hoveredLayer && ph > 0 && hoveredLayer[key] !== void 0) {
|
|
@@ -753,6 +1099,12 @@ function createMotionComponent(Component) {
|
|
|
753
1099
|
const t = pressedLayer[key];
|
|
754
1100
|
v = isColor ? interpolateColor(pp, [0, 1], [v, t]) : v + (t - v) * pp;
|
|
755
1101
|
}
|
|
1102
|
+
if (carried !== null && pc > 0) {
|
|
1103
|
+
const s = carried[key];
|
|
1104
|
+
if (s !== void 0) {
|
|
1105
|
+
v = isColor ? interpolateColor(pc, [0, 1], [v, s]) : v + (s - v) * pc;
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
756
1108
|
if (TRANSFORM_KEY_SET.has(key)) {
|
|
757
1109
|
transform.push(
|
|
758
1110
|
ROTATION_KEYS.has(key) ? { [key]: `${v}deg` } : { [key]: v }
|
|
@@ -775,6 +1127,19 @@ function createMotionComponent(Component) {
|
|
|
775
1127
|
if (hasShadowOffset) {
|
|
776
1128
|
out.shadowOffset = { width: shadowOffsetW, height: shadowOffsetH };
|
|
777
1129
|
}
|
|
1130
|
+
if (hasBoxShadow) {
|
|
1131
|
+
const layers2 = sharedValues.boxShadow.value;
|
|
1132
|
+
const insets = boxShadowInsets.value;
|
|
1133
|
+
if (insets === null) {
|
|
1134
|
+
out.boxShadow = layers2;
|
|
1135
|
+
} else {
|
|
1136
|
+
const withInset = [];
|
|
1137
|
+
for (let i = 0; i < layers2.length; i++) {
|
|
1138
|
+
withInset.push({ ...layers2[i], inset: insets[i] });
|
|
1139
|
+
}
|
|
1140
|
+
out.boxShadow = withInset;
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
778
1143
|
return out;
|
|
779
1144
|
});
|
|
780
1145
|
const mergedStyle = useMemo(
|
|
@@ -849,7 +1214,9 @@ function useAnimatableSharedValues(init) {
|
|
|
849
1214
|
const width = useSharedValue(init("width"));
|
|
850
1215
|
const height = useSharedValue(init("height"));
|
|
851
1216
|
const borderRadius = useSharedValue(init("borderRadius"));
|
|
852
|
-
const shadowOpacity = useSharedValue(
|
|
1217
|
+
const shadowOpacity = useSharedValue(
|
|
1218
|
+
init("shadowOpacity")
|
|
1219
|
+
);
|
|
853
1220
|
const shadowRadius = useSharedValue(init("shadowRadius"));
|
|
854
1221
|
const elevation = useSharedValue(init("elevation"));
|
|
855
1222
|
const backgroundColor = useSharedValue(
|
|
@@ -865,6 +1232,7 @@ function useAnimatableSharedValues(init) {
|
|
|
865
1232
|
const shadowOffsetHeight = useSharedValue(
|
|
866
1233
|
init("shadowOffsetHeight")
|
|
867
1234
|
);
|
|
1235
|
+
const boxShadow = useSharedValue(init("boxShadow"));
|
|
868
1236
|
const ref = useRef(null);
|
|
869
1237
|
if (ref.current === null) {
|
|
870
1238
|
ref.current = {
|
|
@@ -889,7 +1257,8 @@ function useAnimatableSharedValues(init) {
|
|
|
889
1257
|
tintColor,
|
|
890
1258
|
shadowColor,
|
|
891
1259
|
shadowOffsetWidth,
|
|
892
|
-
shadowOffsetHeight
|
|
1260
|
+
shadowOffsetHeight,
|
|
1261
|
+
boxShadow
|
|
893
1262
|
};
|
|
894
1263
|
}
|
|
895
1264
|
const map = ref.current;
|
|
@@ -974,6 +1343,20 @@ function shadowOffsetAxisFor(key) {
|
|
|
974
1343
|
function shadowOffsetAxisValue(source, axis) {
|
|
975
1344
|
return source?.[axis];
|
|
976
1345
|
}
|
|
1346
|
+
function driveBoxShadow(slot, insetSlot, target, cfg, factory) {
|
|
1347
|
+
const currentLayers = Array.isArray(slot.value) ? slot.value : NO_BOX_SHADOW;
|
|
1348
|
+
const { from, to, insets } = prepareBoxShadowAnimation(
|
|
1349
|
+
{ layers: [...currentLayers], insets: insetSlot.value },
|
|
1350
|
+
target
|
|
1351
|
+
);
|
|
1352
|
+
insetSlot.value = insets;
|
|
1353
|
+
if (from.length !== currentLayers.length) slot.value = from;
|
|
1354
|
+
slot.value = resolveTransition(
|
|
1355
|
+
cfg,
|
|
1356
|
+
to,
|
|
1357
|
+
factory?.("animation", void 0)
|
|
1358
|
+
);
|
|
1359
|
+
}
|
|
977
1360
|
function styleValueFor(flat, key) {
|
|
978
1361
|
if (SHADOW_OFFSET_KEY_SET.has(key)) {
|
|
979
1362
|
return shadowOffsetAxisValue(
|
|
@@ -1090,6 +1473,15 @@ function resolveGestureLayers(gesture) {
|
|
|
1090
1473
|
if (!subState) continue;
|
|
1091
1474
|
const resolved = {};
|
|
1092
1475
|
for (const key of ALL_KEYS) {
|
|
1476
|
+
if (STRUCTURED_KEY_SET.has(key)) {
|
|
1477
|
+
if (__DEV__ && subState[key] !== void 0) {
|
|
1478
|
+
warnOnce(
|
|
1479
|
+
`gesture-structured-${layer}-${key}`,
|
|
1480
|
+
`[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\`.`
|
|
1481
|
+
);
|
|
1482
|
+
}
|
|
1483
|
+
continue;
|
|
1484
|
+
}
|
|
1093
1485
|
if (SHADOW_OFFSET_KEY_SET.has(key)) {
|
|
1094
1486
|
const axis = shadowOffsetAxisFor(key);
|
|
1095
1487
|
const so = subState.shadowOffset;
|
|
@@ -1179,4 +1571,4 @@ function compose(user, ours) {
|
|
|
1179
1571
|
};
|
|
1180
1572
|
}
|
|
1181
1573
|
|
|
1182
|
-
export { Presence, createMotionComponent, usePresence };
|
|
1574
|
+
export { Presence, createMotionComponent, pairBoxShadowLayers, resolveBoxShadowInput, usePresence };
|