@rootnative/inertia 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -2
- package/dist/{chunk-NKA6XR77.js → chunk-3XTVY34H.js} +2 -2
- package/dist/{chunk-V6BTXHZK.mjs → chunk-46P57VMY.mjs} +1 -1
- package/dist/{chunk-IWLU3VDE.js → chunk-BP3Y2SHQ.js} +132 -26
- package/dist/{chunk-TUMNV4P7.mjs → chunk-BQQTHG2V.mjs} +1 -1
- package/dist/{chunk-LYMLQ6WQ.mjs → chunk-CSODMRJ7.mjs} +132 -26
- package/dist/chunk-FNVFV4EY.js +8 -0
- package/dist/chunk-FWQOXA43.js +8 -0
- package/dist/chunk-KBP4LR75.js +8 -0
- package/dist/{chunk-2DHKV2XY.mjs → chunk-O22NXXCZ.mjs} +1 -1
- package/dist/{chunk-HFDZAHWP.mjs → chunk-OQV66TBQ.mjs} +1 -1
- package/dist/{chunk-ZN3PNGHQ.mjs → chunk-SGUHE5CX.mjs} +1 -1
- package/dist/{chunk-TUYHTHVV.js → chunk-W5MC3P4N.js} +2 -2
- package/dist/index.d.mts +10 -8
- package/dist/index.d.ts +10 -8
- package/dist/index.js +41 -28
- package/dist/index.mjs +34 -21
- package/dist/motion/Image.js +3 -3
- package/dist/motion/Image.mjs +2 -2
- package/dist/motion/Pressable.js +3 -3
- package/dist/motion/Pressable.mjs +2 -2
- package/dist/motion/ScrollView.js +3 -3
- package/dist/motion/ScrollView.mjs +2 -2
- package/dist/motion/Text.js +3 -3
- package/dist/motion/Text.mjs +2 -2
- package/dist/motion/View.js +3 -3
- package/dist/motion/View.mjs +2 -2
- package/package.json +1 -1
- package/src/layout/index.ts +1 -0
- package/src/layout/sharedRegistry.ts +51 -2
- package/src/motion/createMotionComponent.tsx +176 -20
- package/src/presence/Presence.tsx +73 -10
- package/src/values/useAnimator.ts +25 -14
- package/src/values/useColorCascade.ts +34 -16
- package/dist/chunk-34Q4UM6V.js +0 -8
- package/dist/chunk-KYJROYCG.js +0 -8
- package/dist/chunk-X5J5M3K3.js +0 -8
package/dist/index.d.mts
CHANGED
|
@@ -355,9 +355,11 @@ declare function useAnimation(target: number, transition?: TransitionInput): Sha
|
|
|
355
355
|
* `<MotionConfig reducedMotion>`. Hand-rolled `resolveTransition` writes
|
|
356
356
|
* silently bypass that setting — a correctness bug this hook fixes.
|
|
357
357
|
*
|
|
358
|
-
* The returned callback is stable
|
|
359
|
-
* the reduced-motion flag
|
|
360
|
-
*
|
|
358
|
+
* The returned callback is identity-stable for the lifetime of the component —
|
|
359
|
+
* it reads the registry and the reduced-motion flag out of refs at call time,
|
|
360
|
+
* so neither a new `<MotionConfig transitions>` map nor a reduced-motion change
|
|
361
|
+
* gives it a new identity. Drop it straight into memoized handlers or a
|
|
362
|
+
* `useCallback` dependency list without churning them.
|
|
361
363
|
*
|
|
362
364
|
* This is not a new animation API — it starts animations in Inertia's existing
|
|
363
365
|
* transition vocabulary, so it does not conflict with the "no imperative-only
|
|
@@ -501,11 +503,11 @@ interface UseColorCascadeOptions {
|
|
|
501
503
|
* hook is not a replacement for it. For a mixed numeric + color cascade, or
|
|
502
504
|
* function-valued layers, drop to a hand-rolled `useAnimatedStyle`.
|
|
503
505
|
*
|
|
504
|
-
* The layer chain is resolved once on the JS thread and
|
|
505
|
-
*
|
|
506
|
-
*
|
|
507
|
-
* `
|
|
508
|
-
*
|
|
506
|
+
* The layer chain is resolved once on the JS thread and kept identity-stable,
|
|
507
|
+
* so a fresh-but-equal `layers` array each render produces no new UI-thread
|
|
508
|
+
* closure (CLAUDE.md principle 8). Changing a colour, the `key`, the base
|
|
509
|
+
* `rest`, the layer count, or **which shared value drives a layer** all rewire
|
|
510
|
+
* the worklet as you'd expect.
|
|
509
511
|
*/
|
|
510
512
|
declare function useColorCascade(rest: string, layers: readonly ColorCascadeLayer[], options?: UseColorCascadeOptions): ReturnType<typeof useAnimatedStyle>;
|
|
511
513
|
|
package/dist/index.d.ts
CHANGED
|
@@ -355,9 +355,11 @@ declare function useAnimation(target: number, transition?: TransitionInput): Sha
|
|
|
355
355
|
* `<MotionConfig reducedMotion>`. Hand-rolled `resolveTransition` writes
|
|
356
356
|
* silently bypass that setting — a correctness bug this hook fixes.
|
|
357
357
|
*
|
|
358
|
-
* The returned callback is stable
|
|
359
|
-
* the reduced-motion flag
|
|
360
|
-
*
|
|
358
|
+
* The returned callback is identity-stable for the lifetime of the component —
|
|
359
|
+
* it reads the registry and the reduced-motion flag out of refs at call time,
|
|
360
|
+
* so neither a new `<MotionConfig transitions>` map nor a reduced-motion change
|
|
361
|
+
* gives it a new identity. Drop it straight into memoized handlers or a
|
|
362
|
+
* `useCallback` dependency list without churning them.
|
|
361
363
|
*
|
|
362
364
|
* This is not a new animation API — it starts animations in Inertia's existing
|
|
363
365
|
* transition vocabulary, so it does not conflict with the "no imperative-only
|
|
@@ -501,11 +503,11 @@ interface UseColorCascadeOptions {
|
|
|
501
503
|
* hook is not a replacement for it. For a mixed numeric + color cascade, or
|
|
502
504
|
* function-valued layers, drop to a hand-rolled `useAnimatedStyle`.
|
|
503
505
|
*
|
|
504
|
-
* The layer chain is resolved once on the JS thread and
|
|
505
|
-
*
|
|
506
|
-
*
|
|
507
|
-
* `
|
|
508
|
-
*
|
|
506
|
+
* The layer chain is resolved once on the JS thread and kept identity-stable,
|
|
507
|
+
* so a fresh-but-equal `layers` array each render produces no new UI-thread
|
|
508
|
+
* closure (CLAUDE.md principle 8). Changing a colour, the `key`, the base
|
|
509
|
+
* `rest`, the layer count, or **which shared value drives a layer** all rewire
|
|
510
|
+
* the worklet as you'd expect.
|
|
509
511
|
*/
|
|
510
512
|
declare function useColorCascade(rest: string, layers: readonly ColorCascadeLayer[], options?: UseColorCascadeOptions): ReturnType<typeof useAnimatedStyle>;
|
|
511
513
|
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var chunk4PEHWDAZ_js = require('./chunk-4PEHWDAZ.js');
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
var
|
|
7
|
-
var
|
|
8
|
-
var
|
|
9
|
-
var
|
|
4
|
+
var chunkFNVFV4EY_js = require('./chunk-FNVFV4EY.js');
|
|
5
|
+
var chunkFWQOXA43_js = require('./chunk-FWQOXA43.js');
|
|
6
|
+
var chunkKBP4LR75_js = require('./chunk-KBP4LR75.js');
|
|
7
|
+
var chunk3XTVY34H_js = require('./chunk-3XTVY34H.js');
|
|
8
|
+
var chunkW5MC3P4N_js = require('./chunk-W5MC3P4N.js');
|
|
9
|
+
var chunkBP3Y2SHQ_js = require('./chunk-BP3Y2SHQ.js');
|
|
10
10
|
var chunk7AOERN53_js = require('./chunk-7AOERN53.js');
|
|
11
11
|
var chunkPTRF47DA_js = require('./chunk-PTRF47DA.js');
|
|
12
12
|
var react = require('react');
|
|
@@ -15,11 +15,11 @@ var reactNativeWorklets = require('react-native-worklets');
|
|
|
15
15
|
|
|
16
16
|
// src/motion/index.ts
|
|
17
17
|
var Motion = {
|
|
18
|
-
View:
|
|
19
|
-
Text:
|
|
20
|
-
Image:
|
|
21
|
-
Pressable:
|
|
22
|
-
ScrollView:
|
|
18
|
+
View: chunkFNVFV4EY_js.MotionView,
|
|
19
|
+
Text: chunkFWQOXA43_js.MotionText,
|
|
20
|
+
Image: chunkKBP4LR75_js.MotionImage,
|
|
21
|
+
Pressable: chunk3XTVY34H_js.MotionPressable,
|
|
22
|
+
ScrollView: chunkW5MC3P4N_js.MotionScrollView
|
|
23
23
|
};
|
|
24
24
|
function useAnimation(target, transition) {
|
|
25
25
|
const output = reactNativeReanimated.useSharedValue(target);
|
|
@@ -41,14 +41,15 @@ function useAnimation(target, transition) {
|
|
|
41
41
|
function useAnimator() {
|
|
42
42
|
const registry = chunk7AOERN53_js.useNamedTransitions();
|
|
43
43
|
const shouldReduceMotion = chunk7AOERN53_js.useShouldReduceMotion();
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
44
|
+
const registryRef = react.useRef(registry);
|
|
45
|
+
registryRef.current = registry;
|
|
46
|
+
const reduceMotionRef = react.useRef(shouldReduceMotion);
|
|
47
|
+
reduceMotionRef.current = shouldReduceMotion;
|
|
48
|
+
return react.useCallback((value, to, transition) => {
|
|
49
|
+
const resolved = chunk7AOERN53_js.resolveNamedTransition(transition, registryRef.current);
|
|
50
|
+
const cfg = reduceMotionRef.current ? { type: "no-animation" } : resolved ?? { type: "spring" };
|
|
51
|
+
value.value = chunkPTRF47DA_js.resolveTransition(cfg, to);
|
|
52
|
+
}, []);
|
|
52
53
|
}
|
|
53
54
|
function useSpring(target, config) {
|
|
54
55
|
const spring = resolveSpringInput(config, chunk7AOERN53_js.useNamedTransitions());
|
|
@@ -119,7 +120,19 @@ function useColorCascade(rest, layers, options) {
|
|
|
119
120
|
const key = options?.key ?? "backgroundColor";
|
|
120
121
|
const sig = `${key}|${rest}|${layers.length}|${layers.map((l) => l.color).join(",")}`;
|
|
121
122
|
const colors = react.useMemo(() => layers.map((l) => l.color), [sig]);
|
|
122
|
-
const
|
|
123
|
+
const progressRef = react.useRef([]);
|
|
124
|
+
const prevProgress = progressRef.current;
|
|
125
|
+
let progressChanged = prevProgress.length !== layers.length;
|
|
126
|
+
if (!progressChanged) {
|
|
127
|
+
for (let i = 0; i < layers.length; i++) {
|
|
128
|
+
if (prevProgress[i] !== layers[i].progress) {
|
|
129
|
+
progressChanged = true;
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (progressChanged) progressRef.current = layers.map((l) => l.progress);
|
|
135
|
+
const progressValues = progressRef.current;
|
|
123
136
|
return reactNativeReanimated.useAnimatedStyle(() => {
|
|
124
137
|
"worklet";
|
|
125
138
|
let acc = rest;
|
|
@@ -575,35 +588,35 @@ Object.defineProperty(exports, "useGesture", {
|
|
|
575
588
|
});
|
|
576
589
|
Object.defineProperty(exports, "MotionView", {
|
|
577
590
|
enumerable: true,
|
|
578
|
-
get: function () { return
|
|
591
|
+
get: function () { return chunkFNVFV4EY_js.MotionView; }
|
|
579
592
|
});
|
|
580
593
|
Object.defineProperty(exports, "MotionText", {
|
|
581
594
|
enumerable: true,
|
|
582
|
-
get: function () { return
|
|
595
|
+
get: function () { return chunkFWQOXA43_js.MotionText; }
|
|
583
596
|
});
|
|
584
597
|
Object.defineProperty(exports, "MotionImage", {
|
|
585
598
|
enumerable: true,
|
|
586
|
-
get: function () { return
|
|
599
|
+
get: function () { return chunkKBP4LR75_js.MotionImage; }
|
|
587
600
|
});
|
|
588
601
|
Object.defineProperty(exports, "MotionPressable", {
|
|
589
602
|
enumerable: true,
|
|
590
|
-
get: function () { return
|
|
603
|
+
get: function () { return chunk3XTVY34H_js.MotionPressable; }
|
|
591
604
|
});
|
|
592
605
|
Object.defineProperty(exports, "MotionScrollView", {
|
|
593
606
|
enumerable: true,
|
|
594
|
-
get: function () { return
|
|
607
|
+
get: function () { return chunkW5MC3P4N_js.MotionScrollView; }
|
|
595
608
|
});
|
|
596
609
|
Object.defineProperty(exports, "Presence", {
|
|
597
610
|
enumerable: true,
|
|
598
|
-
get: function () { return
|
|
611
|
+
get: function () { return chunkBP3Y2SHQ_js.Presence; }
|
|
599
612
|
});
|
|
600
613
|
Object.defineProperty(exports, "createMotionComponent", {
|
|
601
614
|
enumerable: true,
|
|
602
|
-
get: function () { return
|
|
615
|
+
get: function () { return chunkBP3Y2SHQ_js.createMotionComponent; }
|
|
603
616
|
});
|
|
604
617
|
Object.defineProperty(exports, "usePresence", {
|
|
605
618
|
enumerable: true,
|
|
606
|
-
get: function () { return
|
|
619
|
+
get: function () { return chunkBP3Y2SHQ_js.usePresence; }
|
|
607
620
|
});
|
|
608
621
|
Object.defineProperty(exports, "MotionConfig", {
|
|
609
622
|
enumerable: true,
|
package/dist/index.mjs
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
export { useGesture } from './chunk-RGNX6UZN.mjs';
|
|
2
|
-
import { MotionView } from './chunk-
|
|
3
|
-
export { MotionView } from './chunk-
|
|
4
|
-
import { MotionText } from './chunk-
|
|
5
|
-
export { MotionText } from './chunk-
|
|
6
|
-
import { MotionImage } from './chunk-
|
|
7
|
-
export { MotionImage } from './chunk-
|
|
8
|
-
import { MotionPressable } from './chunk-
|
|
9
|
-
export { MotionPressable } from './chunk-
|
|
10
|
-
import { MotionScrollView } from './chunk-
|
|
11
|
-
export { MotionScrollView } from './chunk-
|
|
12
|
-
export { Presence, createMotionComponent, usePresence } from './chunk-
|
|
2
|
+
import { MotionView } from './chunk-BQQTHG2V.mjs';
|
|
3
|
+
export { MotionView } from './chunk-BQQTHG2V.mjs';
|
|
4
|
+
import { MotionText } from './chunk-SGUHE5CX.mjs';
|
|
5
|
+
export { MotionText } from './chunk-SGUHE5CX.mjs';
|
|
6
|
+
import { MotionImage } from './chunk-O22NXXCZ.mjs';
|
|
7
|
+
export { MotionImage } from './chunk-O22NXXCZ.mjs';
|
|
8
|
+
import { MotionPressable } from './chunk-46P57VMY.mjs';
|
|
9
|
+
export { MotionPressable } from './chunk-46P57VMY.mjs';
|
|
10
|
+
import { MotionScrollView } from './chunk-OQV66TBQ.mjs';
|
|
11
|
+
export { MotionScrollView } from './chunk-OQV66TBQ.mjs';
|
|
12
|
+
export { Presence, createMotionComponent, usePresence } from './chunk-CSODMRJ7.mjs';
|
|
13
13
|
import { useShouldReduceMotion, resolveNamedTransition, useNamedTransitions, lookupNamedTransition } from './chunk-R63GIUNU.mjs';
|
|
14
14
|
export { MotionConfig, resolveNamedTransition, useMotionConfig, useNamedTransitions, useShouldReduceMotion } from './chunk-R63GIUNU.mjs';
|
|
15
15
|
import { stableSig, resolveTransition, springToReanimated, warnNonWorkletOnce } from './chunk-CY7Y64C3.mjs';
|
|
16
16
|
export { buildReleaseAnimation, cubicBezier, ensureWorkletEasing, resolveAnimatableValue, resolveTransition } from './chunk-CY7Y64C3.mjs';
|
|
17
|
-
import { useEffect, useCallback, useMemo
|
|
17
|
+
import { useEffect, useRef, useCallback, useMemo } from 'react';
|
|
18
18
|
import { useSharedValue, cancelAnimation, withSpring, useAnimatedReaction, useAnimatedStyle, interpolateColor, interpolate, useDerivedValue, Extrapolation, useAnimatedScrollHandler } from 'react-native-reanimated';
|
|
19
19
|
import { isWorkletFunction } from 'react-native-worklets';
|
|
20
20
|
|
|
@@ -46,14 +46,15 @@ function useAnimation(target, transition) {
|
|
|
46
46
|
function useAnimator() {
|
|
47
47
|
const registry = useNamedTransitions();
|
|
48
48
|
const shouldReduceMotion = useShouldReduceMotion();
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
49
|
+
const registryRef = useRef(registry);
|
|
50
|
+
registryRef.current = registry;
|
|
51
|
+
const reduceMotionRef = useRef(shouldReduceMotion);
|
|
52
|
+
reduceMotionRef.current = shouldReduceMotion;
|
|
53
|
+
return useCallback((value, to, transition) => {
|
|
54
|
+
const resolved = resolveNamedTransition(transition, registryRef.current);
|
|
55
|
+
const cfg = reduceMotionRef.current ? { type: "no-animation" } : resolved ?? { type: "spring" };
|
|
56
|
+
value.value = resolveTransition(cfg, to);
|
|
57
|
+
}, []);
|
|
57
58
|
}
|
|
58
59
|
function useSpring(target, config) {
|
|
59
60
|
const spring = resolveSpringInput(config, useNamedTransitions());
|
|
@@ -124,7 +125,19 @@ function useColorCascade(rest, layers, options) {
|
|
|
124
125
|
const key = options?.key ?? "backgroundColor";
|
|
125
126
|
const sig = `${key}|${rest}|${layers.length}|${layers.map((l) => l.color).join(",")}`;
|
|
126
127
|
const colors = useMemo(() => layers.map((l) => l.color), [sig]);
|
|
127
|
-
const
|
|
128
|
+
const progressRef = useRef([]);
|
|
129
|
+
const prevProgress = progressRef.current;
|
|
130
|
+
let progressChanged = prevProgress.length !== layers.length;
|
|
131
|
+
if (!progressChanged) {
|
|
132
|
+
for (let i = 0; i < layers.length; i++) {
|
|
133
|
+
if (prevProgress[i] !== layers[i].progress) {
|
|
134
|
+
progressChanged = true;
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (progressChanged) progressRef.current = layers.map((l) => l.progress);
|
|
140
|
+
const progressValues = progressRef.current;
|
|
128
141
|
return useAnimatedStyle(() => {
|
|
129
142
|
"worklet";
|
|
130
143
|
let acc = rest;
|
package/dist/motion/Image.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
require('../chunk-
|
|
3
|
+
var chunkKBP4LR75_js = require('../chunk-KBP4LR75.js');
|
|
4
|
+
require('../chunk-BP3Y2SHQ.js');
|
|
5
5
|
require('../chunk-7AOERN53.js');
|
|
6
6
|
require('../chunk-PTRF47DA.js');
|
|
7
7
|
|
|
@@ -9,5 +9,5 @@ require('../chunk-PTRF47DA.js');
|
|
|
9
9
|
|
|
10
10
|
Object.defineProperty(exports, "MotionImage", {
|
|
11
11
|
enumerable: true,
|
|
12
|
-
get: function () { return
|
|
12
|
+
get: function () { return chunkKBP4LR75_js.MotionImage; }
|
|
13
13
|
});
|
package/dist/motion/Image.mjs
CHANGED
package/dist/motion/Pressable.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
require('../chunk-
|
|
3
|
+
var chunk3XTVY34H_js = require('../chunk-3XTVY34H.js');
|
|
4
|
+
require('../chunk-BP3Y2SHQ.js');
|
|
5
5
|
require('../chunk-7AOERN53.js');
|
|
6
6
|
require('../chunk-PTRF47DA.js');
|
|
7
7
|
|
|
@@ -9,5 +9,5 @@ require('../chunk-PTRF47DA.js');
|
|
|
9
9
|
|
|
10
10
|
Object.defineProperty(exports, "MotionPressable", {
|
|
11
11
|
enumerable: true,
|
|
12
|
-
get: function () { return
|
|
12
|
+
get: function () { return chunk3XTVY34H_js.MotionPressable; }
|
|
13
13
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
require('../chunk-
|
|
3
|
+
var chunkW5MC3P4N_js = require('../chunk-W5MC3P4N.js');
|
|
4
|
+
require('../chunk-BP3Y2SHQ.js');
|
|
5
5
|
require('../chunk-7AOERN53.js');
|
|
6
6
|
require('../chunk-PTRF47DA.js');
|
|
7
7
|
|
|
@@ -9,5 +9,5 @@ require('../chunk-PTRF47DA.js');
|
|
|
9
9
|
|
|
10
10
|
Object.defineProperty(exports, "MotionScrollView", {
|
|
11
11
|
enumerable: true,
|
|
12
|
-
get: function () { return
|
|
12
|
+
get: function () { return chunkW5MC3P4N_js.MotionScrollView; }
|
|
13
13
|
});
|
package/dist/motion/Text.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
require('../chunk-
|
|
3
|
+
var chunkFWQOXA43_js = require('../chunk-FWQOXA43.js');
|
|
4
|
+
require('../chunk-BP3Y2SHQ.js');
|
|
5
5
|
require('../chunk-7AOERN53.js');
|
|
6
6
|
require('../chunk-PTRF47DA.js');
|
|
7
7
|
|
|
@@ -9,5 +9,5 @@ require('../chunk-PTRF47DA.js');
|
|
|
9
9
|
|
|
10
10
|
Object.defineProperty(exports, "MotionText", {
|
|
11
11
|
enumerable: true,
|
|
12
|
-
get: function () { return
|
|
12
|
+
get: function () { return chunkFWQOXA43_js.MotionText; }
|
|
13
13
|
});
|
package/dist/motion/Text.mjs
CHANGED
package/dist/motion/View.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
require('../chunk-
|
|
3
|
+
var chunkFNVFV4EY_js = require('../chunk-FNVFV4EY.js');
|
|
4
|
+
require('../chunk-BP3Y2SHQ.js');
|
|
5
5
|
require('../chunk-7AOERN53.js');
|
|
6
6
|
require('../chunk-PTRF47DA.js');
|
|
7
7
|
|
|
@@ -9,5 +9,5 @@ require('../chunk-PTRF47DA.js');
|
|
|
9
9
|
|
|
10
10
|
Object.defineProperty(exports, "MotionView", {
|
|
11
11
|
enumerable: true,
|
|
12
|
-
get: function () { return
|
|
12
|
+
get: function () { return chunkFNVFV4EY_js.MotionView; }
|
|
13
13
|
});
|
package/dist/motion/View.mjs
CHANGED
package/package.json
CHANGED
package/src/layout/index.ts
CHANGED
|
@@ -51,6 +51,37 @@ export const SHARED_LAYOUT_TTL_MS = 1000
|
|
|
51
51
|
*/
|
|
52
52
|
let now = (): number => Date.now()
|
|
53
53
|
|
|
54
|
+
/**
|
|
55
|
+
* When the last expiry sweep ran, so the scan is amortized to at most once per
|
|
56
|
+
* TTL window rather than running on every write.
|
|
57
|
+
*/
|
|
58
|
+
let lastSweep = 0
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Drop every entry whose TTL has passed.
|
|
62
|
+
*
|
|
63
|
+
* Without this the map only ever shrank via `consumeLayout` / `peekSharedLayout`,
|
|
64
|
+
* so a `layoutId` that unmounted and was never remounted left its rect behind
|
|
65
|
+
* for the lifetime of the process. Bounded by distinct-id count, which is small
|
|
66
|
+
* for a handful of hero images but not for per-item ids in a long-lived list
|
|
67
|
+
* (`layoutId={`photo-${item.id}`}`).
|
|
68
|
+
*
|
|
69
|
+
* Sweeping a *live* element's entry is harmless: while mounted it re-registers
|
|
70
|
+
* on every `onLayout`, and on unmount `releaseLayout` re-adds it with a fresh
|
|
71
|
+
* TTL. So the only thing an over-eager sweep can cost is a FLIP source that was
|
|
72
|
+
* already too old to be used.
|
|
73
|
+
*
|
|
74
|
+
* Time-gated so a burst of layout events doesn't turn into a burst of full
|
|
75
|
+
* scans — worst case an expired entry survives one extra TTL window.
|
|
76
|
+
*/
|
|
77
|
+
function sweepExpired(at: number): void {
|
|
78
|
+
if (at - lastSweep < SHARED_LAYOUT_TTL_MS) return
|
|
79
|
+
lastSweep = at
|
|
80
|
+
for (const [id, entry] of REGISTRY) {
|
|
81
|
+
if (entry.expiresAt < at) REGISTRY.delete(id)
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
54
85
|
/**
|
|
55
86
|
* Update the latest known rect for `id`. Called on every `onLayout` of a
|
|
56
87
|
* Motion primitive with `layoutId` set so the registry always holds a
|
|
@@ -58,7 +89,9 @@ let now = (): number => Date.now()
|
|
|
58
89
|
* transition. Resets the TTL each call.
|
|
59
90
|
*/
|
|
60
91
|
export function registerLayout(id: string, rect: SharedRect): void {
|
|
61
|
-
|
|
92
|
+
const at = now()
|
|
93
|
+
sweepExpired(at)
|
|
94
|
+
REGISTRY.set(id, { rect, expiresAt: at + SHARED_LAYOUT_TTL_MS })
|
|
62
95
|
}
|
|
63
96
|
|
|
64
97
|
/**
|
|
@@ -67,7 +100,9 @@ export function registerLayout(id: string, rect: SharedRect): void {
|
|
|
67
100
|
* is purely intent-documenting at the call site.
|
|
68
101
|
*/
|
|
69
102
|
export function releaseLayout(id: string, rect: SharedRect): void {
|
|
70
|
-
|
|
103
|
+
const at = now()
|
|
104
|
+
sweepExpired(at)
|
|
105
|
+
REGISTRY.set(id, { rect, expiresAt: at + SHARED_LAYOUT_TTL_MS })
|
|
71
106
|
}
|
|
72
107
|
|
|
73
108
|
/**
|
|
@@ -88,6 +123,7 @@ export function consumeLayout(id: string): SharedRect | undefined {
|
|
|
88
123
|
/** Drop all entries. Tests use this to isolate between cases. */
|
|
89
124
|
export function clearSharedRegistry(): void {
|
|
90
125
|
REGISTRY.clear()
|
|
126
|
+
lastSweep = 0
|
|
91
127
|
}
|
|
92
128
|
|
|
93
129
|
/**
|
|
@@ -108,4 +144,17 @@ export function peekSharedLayout(id: string): SharedRect | undefined {
|
|
|
108
144
|
*/
|
|
109
145
|
export function __setSharedLayoutClock(fn: (() => number) | undefined): void {
|
|
110
146
|
now = fn ?? Date.now
|
|
147
|
+
// Swapping the clock makes the previous sweep timestamp meaningless — a
|
|
148
|
+
// stubbed clock usually starts near 0, which would otherwise suppress every
|
|
149
|
+
// sweep until it caught up past the real-time value recorded earlier.
|
|
150
|
+
lastSweep = 0
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Test hook: how many entries the registry is holding, expired or not. Used to
|
|
155
|
+
* assert that released-but-never-consumed rects are actually evicted. Not
|
|
156
|
+
* exported from the package root — reachable only from inside the workspace.
|
|
157
|
+
*/
|
|
158
|
+
export function __sharedRegistrySize(): number {
|
|
159
|
+
return REGISTRY.size
|
|
111
160
|
}
|