@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.
- package/CHANGELOG.md +63 -5
- package/README.md +5 -3
- package/dist/{chunk-ZN3PNGHQ.mjs → chunk-4ASOELLA.mjs} +1 -1
- package/dist/{chunk-LYMLQ6WQ.mjs → chunk-55W7BNO2.mjs} +604 -106
- package/dist/chunk-5SRD2WCO.js +8 -0
- package/dist/{chunk-PTRF47DA.js → chunk-7A6WTXNK.js} +10 -3
- package/dist/{chunk-NKA6XR77.js → chunk-CENTULW6.js} +2 -2
- package/dist/{chunk-4PEHWDAZ.js → chunk-D5KAHWMC.js} +7 -7
- package/dist/{chunk-2DHKV2XY.mjs → chunk-J5Q46OPW.mjs} +1 -1
- package/dist/{chunk-RGNX6UZN.mjs → chunk-K3CLP74S.mjs} +2 -2
- package/dist/{chunk-IWLU3VDE.js → chunk-MYE5NMXW.js} +623 -123
- package/dist/{chunk-HFDZAHWP.mjs → chunk-NAOXQJ7U.mjs} +1 -1
- package/dist/{chunk-R63GIUNU.mjs → chunk-QKC3APP4.mjs} +1 -1
- package/dist/{chunk-V6BTXHZK.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-TUYHTHVV.js → chunk-XMEVPEMH.js} +2 -2
- package/dist/{chunk-TUMNV4P7.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 +14 -12
- package/dist/index.d.ts +14 -12
- package/dist/index.js +68 -176
- package/dist/index.mjs +40 -147
- 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 +11 -0
- package/src/layout/measureWindow.ts +135 -0
- package/src/layout/sharedRegistry.ts +156 -18
- package/src/layout/useSharedLayout.ts +256 -91
- package/src/motion/createMotionComponent.tsx +550 -55
- package/src/motion/installCheck.ts +1 -1
- package/src/presence/Presence.tsx +73 -10
- package/src/transitions/index.ts +1 -1
- package/src/types.ts +52 -12
- package/src/values/useAnimator.ts +25 -14
- package/src/values/useColorCascade.ts +34 -16
- package/src/values/useColorTransition.ts +1 -1
- package/dist/chunk-34Q4UM6V.js +0 -8
- package/dist/chunk-KYJROYCG.js +0 -8
- package/dist/chunk-X5J5M3K3.js +0 -8
|
@@ -41,7 +41,7 @@ export function ensureReanimatedInstalled(): void {
|
|
|
41
41
|
const major = parseInt(version.split('.')[0] ?? '0', 10)
|
|
42
42
|
if (major < 4) {
|
|
43
43
|
console.error(
|
|
44
|
-
`[inertia] react-native-reanimated
|
|
44
|
+
`[inertia] react-native-reanimated ${version} is installed, but @rootnative/inertia requires 4.0.0 or later. ` +
|
|
45
45
|
`Upgrade with \`pnpm add react-native-reanimated@^4\` (or your package manager's equivalent).`,
|
|
46
46
|
)
|
|
47
47
|
return
|
|
@@ -63,6 +63,20 @@ export function Presence({ children }: { children: ReactNode }) {
|
|
|
63
63
|
// synchronously alongside the setState call.
|
|
64
64
|
const prevIncomingRef = useRef<ReactElement[]>(incoming)
|
|
65
65
|
|
|
66
|
+
// Render order from the previous pass, *including* entries that were already
|
|
67
|
+
// exiting. An exiting child is by definition absent from `incoming`, so this
|
|
68
|
+
// is the only record of where it sat among its siblings.
|
|
69
|
+
const orderRef = useRef<Key[]>([])
|
|
70
|
+
|
|
71
|
+
// The exiting map this render should actually render with. On the render
|
|
72
|
+
// that detects a departure, `exiting` state is still the pre-departure map —
|
|
73
|
+
// `setExiting` below schedules the update but doesn't apply it here. Ordering
|
|
74
|
+
// has to see the departure immediately: if it doesn't, the key is missing
|
|
75
|
+
// from `orderRef` on the *next* render too, and the walk below (which only
|
|
76
|
+
// visits keys it remembers) would drop the child entirely instead of just
|
|
77
|
+
// misplacing it.
|
|
78
|
+
let pendingExiting: Map<Key, ReactElement> | null = null
|
|
79
|
+
|
|
66
80
|
if (prevIncomingRef.current !== incoming) {
|
|
67
81
|
const prev = prevIncomingRef.current
|
|
68
82
|
prevIncomingRef.current = incoming
|
|
@@ -91,9 +105,14 @@ export function Presence({ children }: { children: ReactNode }) {
|
|
|
91
105
|
}
|
|
92
106
|
}
|
|
93
107
|
|
|
94
|
-
if (next)
|
|
108
|
+
if (next) {
|
|
109
|
+
pendingExiting = next
|
|
110
|
+
setExiting(next)
|
|
111
|
+
}
|
|
95
112
|
}
|
|
96
113
|
|
|
114
|
+
const activeExiting = pendingExiting ?? exiting
|
|
115
|
+
|
|
97
116
|
const handleRemove = useCallback((key: Key) => {
|
|
98
117
|
setExiting((prev) => {
|
|
99
118
|
if (!prev.has(key)) return prev
|
|
@@ -107,20 +126,64 @@ export function Presence({ children }: { children: ReactNode }) {
|
|
|
107
126
|
// one array (rather than two `.map` calls inside a fragment) ensures React
|
|
108
127
|
// reconciles by `key` across positions — when an entry moves from
|
|
109
128
|
// present-list to exiting-list, the component instance persists.
|
|
110
|
-
|
|
129
|
+
//
|
|
130
|
+
// Exiting entries are spliced back in at the position they held, not
|
|
131
|
+
// appended. React reconciles this array by key, so appending *moves* the
|
|
132
|
+
// node: removing the middle of `a, b, c` rendered `a, c, b` and the
|
|
133
|
+
// departing row visibly jumped to the end before it had finished animating
|
|
134
|
+
// out. Absolutely-positioned overlays (popovers, sheets) never showed it;
|
|
135
|
+
// any list or column did.
|
|
136
|
+
const byKey = new Map<Key, ReactElement>()
|
|
137
|
+
const presentKeys = new Set<Key>()
|
|
138
|
+
const order: Key[] = []
|
|
111
139
|
for (const el of incoming) {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
})
|
|
140
|
+
const key = el.key as Key
|
|
141
|
+
byKey.set(key, el)
|
|
142
|
+
presentKeys.add(key)
|
|
143
|
+
order.push(key)
|
|
117
144
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
145
|
+
|
|
146
|
+
// Walk the remembered order so that several adjacent departures keep their
|
|
147
|
+
// relative order, and anchor each one immediately after the nearest
|
|
148
|
+
// preceding sibling that is still rendered. No surviving predecessor means
|
|
149
|
+
// it was at the front, so it goes back to the front.
|
|
150
|
+
const prevOrder = orderRef.current
|
|
151
|
+
for (let i = 0; i < prevOrder.length; i++) {
|
|
152
|
+
const key = prevOrder[i]!
|
|
153
|
+
const departing = activeExiting.get(key)
|
|
154
|
+
if (!departing || byKey.has(key)) continue
|
|
155
|
+
let insertAt = 0
|
|
156
|
+
for (let j = i - 1; j >= 0; j--) {
|
|
157
|
+
const anchor = order.indexOf(prevOrder[j]!)
|
|
158
|
+
if (anchor !== -1) {
|
|
159
|
+
insertAt = anchor + 1
|
|
160
|
+
break
|
|
161
|
+
}
|
|
121
162
|
}
|
|
163
|
+
byKey.set(key, departing)
|
|
164
|
+
order.splice(insertAt, 0, key)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Safety net: an exiting child the remembered order never saw still has to
|
|
168
|
+
// render, or it would unmount with no exit animation at all. Appending is
|
|
169
|
+
// the old (wrong-position) behaviour, which is strictly better than dropping
|
|
170
|
+
// it — in practice `activeExiting` keeps this loop empty.
|
|
171
|
+
for (const [key, el] of activeExiting) {
|
|
172
|
+
if (byKey.has(key)) continue
|
|
173
|
+
byKey.set(key, el)
|
|
174
|
+
order.push(key)
|
|
122
175
|
}
|
|
123
176
|
|
|
177
|
+
orderRef.current = order
|
|
178
|
+
|
|
179
|
+
// A live `incoming` entry always wins: a key that returns mid-exit is
|
|
180
|
+
// present again, and the same instance interrupts back toward `animate`.
|
|
181
|
+
const renderList: RenderEntry[] = order.map((key) => ({
|
|
182
|
+
key,
|
|
183
|
+
element: byKey.get(key)!,
|
|
184
|
+
isPresent: presentKeys.has(key),
|
|
185
|
+
}))
|
|
186
|
+
|
|
124
187
|
return (
|
|
125
188
|
<>
|
|
126
189
|
{renderList.map(({ key, element, isPresent }) => (
|
package/src/transitions/index.ts
CHANGED
package/src/types.ts
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
type ReactElement,
|
|
5
5
|
type Ref,
|
|
6
6
|
} from 'react'
|
|
7
|
-
import { type StyleProp } from 'react-native'
|
|
7
|
+
import { type BoxShadowValue, type StyleProp } from 'react-native'
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* A single animation step's destination, optionally overriding the transition
|
|
@@ -184,6 +184,39 @@ type AnimatableTransformExtras = {
|
|
|
184
184
|
rotateY?: AnimatableValue<number>
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
+
/**
|
|
188
|
+
* Target shape for the `boxShadow` key on `animate` / `initial` / `exit`: a
|
|
189
|
+
* CSS `box-shadow` string, or RN's own array-of-layers form.
|
|
190
|
+
*
|
|
191
|
+
* Both endpoints of a `boxShadow` animation are normalized to a common layer
|
|
192
|
+
* count on the JS thread, so a two-layer shadow can animate to a one-layer one
|
|
193
|
+
* (the short side is padded with a transparent layer, as CSS transitions do).
|
|
194
|
+
* A layer that is `inset` on one side and not the other is not interpolable
|
|
195
|
+
* and throws.
|
|
196
|
+
*/
|
|
197
|
+
export type BoxShadowInput = string | ReadonlyArray<BoxShadowValue>
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Keys whose animatable form deliberately departs from the generic
|
|
201
|
+
* `AnimatableValue<S[K]>` mapping.
|
|
202
|
+
*
|
|
203
|
+
* `boxShadow` is the only member. Its natural value is already an array, which
|
|
204
|
+
* collides head-on with `AnimatableValue`'s keyframe-sequence form — nothing
|
|
205
|
+
* distinguishes `[layerA, layerB]` (one two-layer shadow) from a two-step
|
|
206
|
+
* sequence. The array slot is given to layers, which is the shape RN itself
|
|
207
|
+
* uses and by far the common case, and sequences are unsupported on this key.
|
|
208
|
+
* This mirrors the single-value-only contract `shadowOffset` has carried since
|
|
209
|
+
* `0.0.1`. Per-property transitions are unaffected: `transition={{ boxShadow:
|
|
210
|
+
* { type: 'timing' } }}` works as it does for every other key.
|
|
211
|
+
*
|
|
212
|
+
* Conditional on `S` so the key only appears where the underlying style
|
|
213
|
+
* actually has it, rather than being bolted onto every primitive.
|
|
214
|
+
*/
|
|
215
|
+
type AnimatableStructuredExtras<S> = 'boxShadow' extends keyof S
|
|
216
|
+
? { boxShadow?: BoxShadowInput }
|
|
217
|
+
: // eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
218
|
+
{}
|
|
219
|
+
|
|
187
220
|
/**
|
|
188
221
|
* The animation state shape inferred from the underlying component's style
|
|
189
222
|
* prop. We narrow to the value side of `style` so consumers see ViewStyle on
|
|
@@ -200,7 +233,9 @@ type _StyleValue<T> = Exclude<T, (...args: any[]) => any>
|
|
|
200
233
|
|
|
201
234
|
export type AnimateStyle<C> = C extends { style?: infer Raw }
|
|
202
235
|
? _StyleValue<Raw> extends StyleProp<infer S>
|
|
203
|
-
? { [K in keyof S]?: AnimatableValue<S[K]> } &
|
|
236
|
+
? Omit<{ [K in keyof S]?: AnimatableValue<S[K]> }, 'boxShadow'> &
|
|
237
|
+
AnimatableTransformExtras &
|
|
238
|
+
AnimatableStructuredExtras<S>
|
|
204
239
|
: never
|
|
205
240
|
: never
|
|
206
241
|
|
|
@@ -379,19 +414,24 @@ export interface MotionProps<C, V extends VariantsMap<C> = VariantsMap<C>> {
|
|
|
379
414
|
* recorded rect to its natural position via a FLIP transform stack.
|
|
380
415
|
*
|
|
381
416
|
* Reanimated 4 removed the `sharedTransitionTag` API — `layoutId` is the
|
|
382
|
-
* Inertia-side measure-based replacement. Rects are recorded in
|
|
383
|
-
*
|
|
384
|
-
* source and target
|
|
385
|
-
*
|
|
386
|
-
*
|
|
417
|
+
* Inertia-side measure-based replacement. Rects are recorded in **window**
|
|
418
|
+
* coordinates wherever the host can be measured synchronously (Fabric),
|
|
419
|
+
* which is what lets a source and target sit under containers at different
|
|
420
|
+
* screen offsets; elsewhere both fall back to the parent-relative
|
|
421
|
+
* coordinates `onLayout` reports. A source and target that ended up in
|
|
422
|
+
* different spaces skip the animation rather than play a wrong one.
|
|
387
423
|
*
|
|
388
424
|
* The same `transition` prop drives the FLIP animation (spring by
|
|
389
425
|
* default; `'timing'` honored; `'decay'` downgrades to spring; reduced
|
|
390
|
-
* motion skips the transition).
|
|
391
|
-
*
|
|
392
|
-
*
|
|
393
|
-
*
|
|
394
|
-
*
|
|
426
|
+
* motion skips the transition). Alongside the rect, a fixed set of style
|
|
427
|
+
* keys is carried from the source and crossfaded out on that same
|
|
428
|
+
* transition: `opacity`, `borderRadius`, `backgroundColor`, `borderColor`,
|
|
429
|
+
* `color`, `tintColor`. Transform keys are not carried — the FLIP owns
|
|
430
|
+
* them — and a key only participates when the element already has a value
|
|
431
|
+
* for it, from a record or from its static `style`.
|
|
432
|
+
*
|
|
433
|
+
* Two simultaneously-mounted primitives sharing the same `layoutId` are
|
|
434
|
+
* undefined behavior; pick a primitive per id at a time.
|
|
395
435
|
*/
|
|
396
436
|
layoutId?: string
|
|
397
437
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useCallback } from 'react'
|
|
1
|
+
import { useCallback, useRef } from 'react'
|
|
2
2
|
import { type SharedValue } from 'react-native-reanimated'
|
|
3
3
|
import {
|
|
4
4
|
resolveNamedTransition,
|
|
@@ -24,9 +24,11 @@ import { type TransitionInput } from '../types'
|
|
|
24
24
|
* `<MotionConfig reducedMotion>`. Hand-rolled `resolveTransition` writes
|
|
25
25
|
* silently bypass that setting — a correctness bug this hook fixes.
|
|
26
26
|
*
|
|
27
|
-
* The returned callback is stable
|
|
28
|
-
* the reduced-motion flag
|
|
29
|
-
*
|
|
27
|
+
* The returned callback is identity-stable for the lifetime of the component —
|
|
28
|
+
* it reads the registry and the reduced-motion flag out of refs at call time,
|
|
29
|
+
* so neither a new `<MotionConfig transitions>` map nor a reduced-motion change
|
|
30
|
+
* gives it a new identity. Drop it straight into memoized handlers or a
|
|
31
|
+
* `useCallback` dependency list without churning them.
|
|
30
32
|
*
|
|
31
33
|
* This is not a new animation API — it starts animations in Inertia's existing
|
|
32
34
|
* transition vocabulary, so it does not conflict with the "no imperative-only
|
|
@@ -59,14 +61,23 @@ export function useAnimator(): Animator {
|
|
|
59
61
|
const registry = useNamedTransitions()
|
|
60
62
|
const shouldReduceMotion = useShouldReduceMotion()
|
|
61
63
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
)
|
|
64
|
+
// Latest context values behind refs, so the callback below can close over
|
|
65
|
+
// nothing that changes. Depending on them directly would hand back a new
|
|
66
|
+
// identity whenever a provider re-published its registry or the OS
|
|
67
|
+
// reduced-motion flag flipped — which breaks the documented contract that
|
|
68
|
+
// this is safe to drop into a memoized handler. Reading at call time is also
|
|
69
|
+
// strictly more correct: the write always resolves against the registry that
|
|
70
|
+
// is current *when the event fires*, not the one captured at render.
|
|
71
|
+
const registryRef = useRef(registry)
|
|
72
|
+
registryRef.current = registry
|
|
73
|
+
const reduceMotionRef = useRef(shouldReduceMotion)
|
|
74
|
+
reduceMotionRef.current = shouldReduceMotion
|
|
75
|
+
|
|
76
|
+
return useCallback((value, to, transition) => {
|
|
77
|
+
const resolved = resolveNamedTransition(transition, registryRef.current)
|
|
78
|
+
const cfg = reduceMotionRef.current
|
|
79
|
+
? ({ type: 'no-animation' } as const)
|
|
80
|
+
: (resolved ?? ({ type: 'spring' } as const))
|
|
81
|
+
value.value = resolveTransition(cfg, to) as never
|
|
82
|
+
}, [])
|
|
72
83
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useMemo } from 'react'
|
|
1
|
+
import { useMemo, useRef } from 'react'
|
|
2
2
|
import {
|
|
3
3
|
interpolateColor,
|
|
4
4
|
useAnimatedStyle,
|
|
@@ -60,11 +60,11 @@ export interface UseColorCascadeOptions {
|
|
|
60
60
|
* hook is not a replacement for it. For a mixed numeric + color cascade, or
|
|
61
61
|
* function-valued layers, drop to a hand-rolled `useAnimatedStyle`.
|
|
62
62
|
*
|
|
63
|
-
* The layer chain is resolved once on the JS thread and
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
* `
|
|
67
|
-
*
|
|
63
|
+
* The layer chain is resolved once on the JS thread and kept identity-stable,
|
|
64
|
+
* so a fresh-but-equal `layers` array each render produces no new UI-thread
|
|
65
|
+
* closure (CLAUDE.md principle 8). Changing a colour, the `key`, the base
|
|
66
|
+
* `rest`, the layer count, or **which shared value drives a layer** all rewire
|
|
67
|
+
* the worklet as you'd expect.
|
|
68
68
|
*/
|
|
69
69
|
export function useColorCascade(
|
|
70
70
|
rest: string,
|
|
@@ -73,21 +73,39 @@ export function useColorCascade(
|
|
|
73
73
|
): ReturnType<typeof useAnimatedStyle> {
|
|
74
74
|
const key = options?.key ?? 'backgroundColor'
|
|
75
75
|
|
|
76
|
-
// Resolve the layer chain into two flat
|
|
77
|
-
//
|
|
78
|
-
//
|
|
79
|
-
//
|
|
80
|
-
//
|
|
81
|
-
//
|
|
82
|
-
//
|
|
83
|
-
// real change to the chain.
|
|
76
|
+
// Resolve the layer chain into two flat arrays the worklet closes over — the
|
|
77
|
+
// static colors and the live progress shared values. Both must keep a stable
|
|
78
|
+
// identity across renders where nothing really changed, or Reanimated sees a
|
|
79
|
+
// fresh closure dependency and rebuilds the UI-thread worklet every render
|
|
80
|
+
// (CLAUDE.md principle 8).
|
|
81
|
+
//
|
|
82
|
+
// Colors key off a structural signature.
|
|
84
83
|
const sig = `${key}|${rest}|${layers.length}|${layers
|
|
85
84
|
.map((l) => l.color)
|
|
86
85
|
.join(',')}`
|
|
87
86
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
88
87
|
const colors = useMemo(() => layers.map((l) => l.color), [sig])
|
|
89
|
-
|
|
90
|
-
|
|
88
|
+
|
|
89
|
+
// Progress values can't go in that signature — they're objects, not
|
|
90
|
+
// stringifiable. But they can't be excluded from change detection either:
|
|
91
|
+
// swapping *which* shared value drives a layer while its colour stays the
|
|
92
|
+
// same has to rewire the worklet. (It previously didn't: the cascade kept
|
|
93
|
+
// reading the old SV forever, silently.) So compare references directly and
|
|
94
|
+
// rebuild the array only when one actually differs — an equal-but-fresh
|
|
95
|
+
// `layers` literal still yields the same reference and no new worklet.
|
|
96
|
+
const progressRef = useRef<readonly SharedValue<number>[]>([])
|
|
97
|
+
const prevProgress = progressRef.current
|
|
98
|
+
let progressChanged = prevProgress.length !== layers.length
|
|
99
|
+
if (!progressChanged) {
|
|
100
|
+
for (let i = 0; i < layers.length; i++) {
|
|
101
|
+
if (prevProgress[i] !== layers[i]!.progress) {
|
|
102
|
+
progressChanged = true
|
|
103
|
+
break
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (progressChanged) progressRef.current = layers.map((l) => l.progress)
|
|
108
|
+
const progressValues = progressRef.current
|
|
91
109
|
|
|
92
110
|
return useAnimatedStyle(() => {
|
|
93
111
|
'worklet'
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Color style keys understood by React Native that this hook can target.
|
|
9
|
-
* Sticks to the keys that exist on the
|
|
9
|
+
* Sticks to the keys that exist on the animatable surface so the
|
|
10
10
|
* returned style fragment is always a legal RN style.
|
|
11
11
|
*/
|
|
12
12
|
export type ColorStyleKey =
|
package/dist/chunk-34Q4UM6V.js
DELETED
package/dist/chunk-KYJROYCG.js
DELETED
package/dist/chunk-X5J5M3K3.js
DELETED