@unrulysystems/native-motion 0.1.0-alpha.0
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 +16 -0
- package/LICENSE +21 -0
- package/README.md +55 -0
- package/android/build.gradle +24 -0
- package/android/src/main/AndroidManifest.xml +1 -0
- package/android/src/main/java/com/unrulysystems/nativemotion/GestureExclusionModule.kt +55 -0
- package/android/src/main/java/com/unrulysystems/nativemotion/NativeMotionPackage.kt +27 -0
- package/package.json +57 -0
- package/react-native.config.js +14 -0
- package/src/native/driver/instantWindow.ts +31 -0
- package/src/native/driver/strictModeReplay.ts +20 -0
- package/src/native/driver/uiLayoutEngine.ts +845 -0
- package/src/native/driver/uiLayoutGraph.ts +338 -0
- package/src/native/driver/uiValueChannel.ts +4640 -0
- package/src/native/driver/workletDriver.ts +3860 -0
- package/src/native/motion/AnimatePresence.tsx +1605 -0
- package/src/native/motion/LayoutGroup.tsx +163 -0
- package/src/native/motion/MotionConfig.tsx +400 -0
- package/src/native/motion/MotionRoot.tsx +250 -0
- package/src/native/motion/MotionView.tsx +6761 -0
- package/src/native/motion/addScaleCorrector.ts +97 -0
- package/src/native/motion/colorEndpointUiFeed.ts +32 -0
- package/src/native/motion/colorProjection.ts +39 -0
- package/src/native/motion/composeTransform.ts +271 -0
- package/src/native/motion/constraintMeasure.ts +157 -0
- package/src/native/motion/deferredPendingSnapshots.ts +25 -0
- package/src/native/motion/discreteProjection.ts +36 -0
- package/src/native/motion/dragAncestorPanContext.ts +28 -0
- package/src/native/motion/dragControls.ts +152 -0
- package/src/native/motion/dragGestureWiring.ts +1168 -0
- package/src/native/motion/dragHandoffBinding.ts +179 -0
- package/src/native/motion/dragHubStream.ts +756 -0
- package/src/native/motion/dragPropagationLock.ts +57 -0
- package/src/native/motion/driverValueChannel.ts +3288 -0
- package/src/native/motion/externalDragDriver.ts +214 -0
- package/src/native/motion/frameData.ts +31 -0
- package/src/native/motion/gestureBinding.ts +107 -0
- package/src/native/motion/gestureStateGate.ts +563 -0
- package/src/native/motion/gestureStateResolver.ts +286 -0
- package/src/native/motion/identityValueChannelControllerAdapter.ts +2043 -0
- package/src/native/motion/identityValueChannelControllerReconciliation.ts +176 -0
- package/src/native/motion/identityValueChannelLaneMarker.ts +14 -0
- package/src/native/motion/imperativeAnimate.ts +816 -0
- package/src/native/motion/keyframeTiming.ts +7 -0
- package/src/native/motion/layoutIdBinding.ts +261 -0
- package/src/native/motion/layoutIdFlightConfig.ts +51 -0
- package/src/native/motion/layoutProjection.ts +89 -0
- package/src/native/motion/layoutScroll.ts +204 -0
- package/src/native/motion/layoutTransition.ts +1302 -0
- package/src/native/motion/lengthLayoutContext.tsx +100 -0
- package/src/native/motion/lengthLayoutHost.ts +44 -0
- package/src/native/motion/mappedKeys.ts +184 -0
- package/src/native/motion/motionViewController.ts +3180 -0
- package/src/native/motion/nativeHostMarker.ts +22 -0
- package/src/native/motion/panSessionWiring.ts +127 -0
- package/src/native/motion/pathTransition.ts +101 -0
- package/src/native/motion/popLayout.ts +176 -0
- package/src/native/motion/presenceBinding.ts +382 -0
- package/src/native/motion/scaleCorrectorRegistry.ts +123 -0
- package/src/native/motion/scrollValues.ts +260 -0
- package/src/native/motion/serializablePayload.ts +151 -0
- package/src/native/motion/severity.ts +16 -0
- package/src/native/motion/shippedSurface.ts +843 -0
- package/src/native/motion/staticLengthGate.ts +86 -0
- package/src/native/motion/styleBaseGate.ts +72 -0
- package/src/native/motion/styleValueBinding.ts +657 -0
- package/src/native/motion/systemGestureExclusion.ts +61 -0
- package/src/native/motion/tapGestureWiring.ts +215 -0
- package/src/native/motion/transformOrder.ts +38 -0
- package/src/native/motion/transformStringBinding.ts +200 -0
- package/src/native/motion/transformTemplateGate.ts +45 -0
- package/src/native/motion/transitionGate.ts +435 -0
- package/src/native/motion/useAnimate.ts +52 -0
- package/src/native/motion/useCycle.ts +44 -0
- package/src/native/motion/useInstantTransition.ts +68 -0
- package/src/native/motion/useReducedMotion.ts +58 -0
- package/src/native/motion/useScroll.ts +162 -0
- package/src/native/motion/useViewportScroll.ts +29 -0
- package/src/native/motion/valueChannel.ts +7121 -0
- package/src/native/motion/valueHooks.ts +901 -0
- package/src/native/motion/variantChildRegistry.ts +67 -0
- package/src/native/motion/variantContext.tsx +172 -0
- package/src/native/motion/variantProps.ts +598 -0
- package/src/native.ts +159 -0
- package/src/verification/harnessMetrics.ts +78 -0
- package/src/verification/probe/LayoutIdentityWorkletProbe.tsx +251 -0
- package/src/verification/probe/WorkletParityProbe.tsx +162 -0
- package/src/verification/probe/layoutIdentityProbeEngine.ts +429 -0
- package/src/verification/screens/ArcPathChecksScreen.tsx +273 -0
- package/src/verification/screens/BooleanAnimateChecksScreen.tsx +358 -0
- package/src/verification/screens/ChoreographyGalleryScreen.tsx +1010 -0
- package/src/verification/screens/ColorBindingChecksScreen.tsx +568 -0
- package/src/verification/screens/CompletionChecksScreen.tsx +294 -0
- package/src/verification/screens/ConformanceScreen.tsx +573 -0
- package/src/verification/screens/ContentionProbeScreen.tsx +224 -0
- package/src/verification/screens/DriverSmokeScreen.tsx +99 -0
- package/src/verification/screens/DurationOnlyTweenChecksScreen.tsx +294 -0
- package/src/verification/screens/DynamicDragConfigChecksScreen.tsx +237 -0
- package/src/verification/screens/FrameDataChecksScreen.tsx +252 -0
- package/src/verification/screens/GestureChecksScreen.tsx +685 -0
- package/src/verification/screens/InstantTransitionChecksScreen.tsx +839 -0
- package/src/verification/screens/LayoutAnimationStartChecksScreen.tsx +648 -0
- package/src/verification/screens/LayoutChecksScreen.tsx +822 -0
- package/src/verification/screens/LayoutCommitSpikeScreen.tsx +142 -0
- package/src/verification/screens/MotionViewChecksScreen.tsx +930 -0
- package/src/verification/screens/PresenceChecksScreen.tsx +614 -0
- package/src/verification/screens/ReducedMotionChecksScreen.tsx +614 -0
- package/src/verification/screens/RestThresholdChecksScreen.tsx +634 -0
- package/src/verification/screens/ScaleCorrectorChecksScreen.tsx +425 -0
- package/src/verification/screens/SharedLayoutContinuityChecksScreen.tsx +338 -0
- package/src/verification/screens/SharedLayoutCrossfadeChecksScreen.tsx +425 -0
- package/src/verification/screens/TransitionDefaultSelectionChecksScreen.tsx +514 -0
- package/src/verification/screens/ViewportScrollAliasChecksScreen.tsx +303 -0
- package/src/verification/screens/conformanceBanner.ts +21 -0
- package/src/verification/screens/proofConsoleTap.ts +18 -0
- package/src/verification.ts +47 -0
- package/src/web.ts +98 -0
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
// The gesture-state priority resolver (R6, REQ-API-031) as pure, host-agnostic logic. The
|
|
2
|
+
// pinned law (motion-dom variantPriorityOrder + animation-state removed-key handling): a
|
|
3
|
+
// layer's activation OVERLAYS the keys it names unless a higher ACTIVE layer holds them; its
|
|
4
|
+
// deactivation REVERTS each named key to the next-lower ACTIVE layer's definition — animated
|
|
5
|
+
// with the DESTINATION layer's transition (R6-F1), else the element transition — falling to
|
|
6
|
+
// the caller's base resolution (REQ-API-011) when no layer defines the key. Unnamed keys
|
|
7
|
+
// never move (the partial-overlay law, REQ-API-002/012). MotionView wires recognizer
|
|
8
|
+
// lifecycles to setActive and applies the returned retargets through the existing update lane.
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
ORCHESTRATION_OPTION_KEYS,
|
|
12
|
+
type Target,
|
|
13
|
+
type Transition,
|
|
14
|
+
} from '@unrulysystems/native-motion-core'
|
|
15
|
+
|
|
16
|
+
const ORCHESTRATION_KEY_SET: ReadonlySet<string> = new Set(ORCHESTRATION_OPTION_KEYS)
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The driver-lane strip (T21, REQ-API-053): the tree-lane orchestration options execute at the
|
|
20
|
+
* variant-tree altitude (MotionView's orchestration channel) — a driver-facing consumer of the
|
|
21
|
+
* same bag takes the remainder. A bag without the keys flows by IDENTITY.
|
|
22
|
+
*/
|
|
23
|
+
export function stripOrchestrationOptions(
|
|
24
|
+
transition: Transition | undefined,
|
|
25
|
+
): Transition | undefined {
|
|
26
|
+
if (transition === undefined) return undefined
|
|
27
|
+
const keys = Reflect.ownKeys(transition)
|
|
28
|
+
if (!keys.some((key) => typeof key === 'string' && ORCHESTRATION_KEY_SET.has(key))) {
|
|
29
|
+
return transition
|
|
30
|
+
}
|
|
31
|
+
const stripped: Record<PropertyKey, unknown> = {}
|
|
32
|
+
for (const key of keys) {
|
|
33
|
+
if (typeof key !== 'string' || ORCHESTRATION_KEY_SET.has(key)) continue
|
|
34
|
+
stripped[key] = (transition as Record<string, unknown>)[key]
|
|
35
|
+
}
|
|
36
|
+
return stripped as Transition
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** The shipped subset of the pinned variantPriorityOrder, LOW to HIGH. */
|
|
40
|
+
export const GESTURE_STATE_PRIORITY = ['animate', 'whileTap', 'whileDrag'] as const
|
|
41
|
+
export type GestureStateLayerName = (typeof GESTURE_STATE_PRIORITY)[number]
|
|
42
|
+
|
|
43
|
+
export interface GestureStateLayer {
|
|
44
|
+
readonly target: Target
|
|
45
|
+
/** Runtime-only functional definition, materialized exactly once on the activation edge. */
|
|
46
|
+
readonly resolveAtActivation?: (() => GestureStateLayer) | undefined
|
|
47
|
+
/** The layer's own transition; absent → the element transition applies (R6-F1). */
|
|
48
|
+
readonly transition?: Transition | undefined
|
|
49
|
+
/**
|
|
50
|
+
* R7 (REQ-API-032 law b): per-key attribution from a label-form definition — the
|
|
51
|
+
* transition of the label application that last named the key. Consulted FIRST; an
|
|
52
|
+
* unattributed key falls back down the R6-F1 chain (layer transition, else element).
|
|
53
|
+
*/
|
|
54
|
+
readonly transitions?: Readonly<Record<string, Transition>> | undefined
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface GestureStateRetarget {
|
|
58
|
+
readonly key: string
|
|
59
|
+
readonly value: unknown
|
|
60
|
+
readonly transition: Transition | undefined
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface GestureStateResolver {
|
|
64
|
+
/**
|
|
65
|
+
* Flip a layer's active state; returns the retargets the flip produces, in the layer
|
|
66
|
+
* target's key order. Idempotent: a no-op flip returns nothing.
|
|
67
|
+
*/
|
|
68
|
+
setActive(layer: GestureStateLayerName, active: boolean): GestureStateRetarget[]
|
|
69
|
+
/**
|
|
70
|
+
* Keys currently OWNED by an active non-animate layer — a render-lane animate update must
|
|
71
|
+
* exclude them or it would clobber the live gesture state (motion's protectedKeys law).
|
|
72
|
+
*/
|
|
73
|
+
heldKeys(): ReadonlySet<string>
|
|
74
|
+
/**
|
|
75
|
+
* Reconcile every ACTIVE layer against its LIVE definition (r5 major 2f0ea1c7d3b4): a
|
|
76
|
+
* changed value retargets, a removed key reverts to its lower destination, and a vanished
|
|
77
|
+
* layer deactivates fully (revert everything it applied, clear the active bit — never a
|
|
78
|
+
* latch). Idempotent: an unchanged layer contributes nothing. The caller runs this once
|
|
79
|
+
* per render, after refreshing the live layers.
|
|
80
|
+
*/
|
|
81
|
+
reconcile(): GestureStateRetarget[]
|
|
82
|
+
/**
|
|
83
|
+
* Re-emit every key an active non-animate layer currently OWNS, with the live definition's
|
|
84
|
+
* value and destination transition (review 2d7c3be235a4). The caller runs this on a MEASURE
|
|
85
|
+
* epoch (parent/viewport context change, or a landed intrinsic auto measure): reconcile()
|
|
86
|
+
* compares RAW values, so a context-only change to a measure-resolved target ('50%', 'auto',
|
|
87
|
+
* calc) emits nothing on its own. Numeric re-issues diff to no-ops in the update lane.
|
|
88
|
+
*/
|
|
89
|
+
reissueActiveTargets(): GestureStateRetarget[]
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function createGestureStateResolver(options: {
|
|
93
|
+
/**
|
|
94
|
+
* LIVE layer access (r4 major 19): read at every flip/query, never snapshotted — an animate
|
|
95
|
+
* rerender or a changed gesture target is in force the moment the caller's accessor reflects
|
|
96
|
+
* it (motion's animation-state reads current props the same way).
|
|
97
|
+
*/
|
|
98
|
+
readonly layers: () => Partial<Record<GestureStateLayerName, GestureStateLayer>>
|
|
99
|
+
/** REQ-API-011: the style-base value a key reverts to when no active layer defines it. */
|
|
100
|
+
readonly baseValueFor: (key: string) => unknown
|
|
101
|
+
readonly elementTransition?: (() => Transition | undefined) | undefined
|
|
102
|
+
}): GestureStateResolver {
|
|
103
|
+
const { layers: readLayers, baseValueFor } = options
|
|
104
|
+
const elementTransition = (): Transition | undefined => options.elementTransition?.()
|
|
105
|
+
const active = new Set<GestureStateLayerName>(['animate']) // animate is always active
|
|
106
|
+
// What each ACTIVE layer overlaid (its definition snapshot at activation, kept current by
|
|
107
|
+
// reconcile): deactivation and reconcile revert from THIS, never from the live definition —
|
|
108
|
+
// a definition that changed or vanished while active must still revert what it applied.
|
|
109
|
+
const applied = new Map<GestureStateLayerName, Record<string, unknown>>()
|
|
110
|
+
const activatedDefinitions = new Map<GestureStateLayerName, GestureStateLayer>()
|
|
111
|
+
|
|
112
|
+
const layerIndex = (layer: GestureStateLayerName): number => GESTURE_STATE_PRIORITY.indexOf(layer)
|
|
113
|
+
|
|
114
|
+
const layerFor = (
|
|
115
|
+
name: GestureStateLayerName,
|
|
116
|
+
live: Partial<Record<GestureStateLayerName, GestureStateLayer>> = readLayers(),
|
|
117
|
+
): GestureStateLayer | undefined => activatedDefinitions.get(name) ?? live[name]
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* The R6-F1 chain with R7's per-key attribution first (law b). The winning bag is stripped
|
|
121
|
+
* of tree-lane orchestration options at this single choke point (T21, review r2 major 1):
|
|
122
|
+
* an ANIMATE-layer attribution may legally carry a variant ROOT bag with the keys (the
|
|
123
|
+
* tree lane executes them at label application), but every retarget this resolver emits
|
|
124
|
+
* feeds a property-lane command — a driver-facing read takes the remainder.
|
|
125
|
+
*/
|
|
126
|
+
const transitionFor = (layer: GestureStateLayer, key: string): Transition | undefined =>
|
|
127
|
+
stripOrchestrationOptions(layer.transitions?.[key] ?? layer.transition ?? elementTransition())
|
|
128
|
+
|
|
129
|
+
/** The highest ACTIVE layer defining `key`, or null. */
|
|
130
|
+
const owningLayer = (key: string): GestureStateLayerName | null => {
|
|
131
|
+
const layers = readLayers()
|
|
132
|
+
for (let i = GESTURE_STATE_PRIORITY.length - 1; i >= 0; i--) {
|
|
133
|
+
const name = GESTURE_STATE_PRIORITY[i]!
|
|
134
|
+
if (!active.has(name)) continue
|
|
135
|
+
const layer = layerFor(name, layers)
|
|
136
|
+
if (layer !== undefined && key in layer.target) return name
|
|
137
|
+
}
|
|
138
|
+
return null
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const destinationFor = (key: string): GestureStateRetarget | null => {
|
|
142
|
+
const owner = owningLayer(key)
|
|
143
|
+
if (owner !== null) {
|
|
144
|
+
const layer = layerFor(owner)!
|
|
145
|
+
return {
|
|
146
|
+
key,
|
|
147
|
+
value: (layer.target as Record<string, unknown>)[key],
|
|
148
|
+
transition: transitionFor(layer, key),
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
const base = baseValueFor(key)
|
|
152
|
+
// No layer and no base: the resolver never invents a destination — the caller's mount
|
|
153
|
+
// law owns that case (REQ-API-011 resolved the first paint; an unmoved key stays put).
|
|
154
|
+
if (base === undefined) return null
|
|
155
|
+
return { key, value: base, transition: elementTransition() }
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* The applied snapshot of an ACTIVE layer. Activation always records one (setActive's
|
|
160
|
+
* activate path), so absence is the resolver's own bookkeeping broken — degrading to an
|
|
161
|
+
* empty target would silently turn a release into a no-op and leave values stuck
|
|
162
|
+
* (r6 minor 3d497c80a16b); fail loud instead.
|
|
163
|
+
*/
|
|
164
|
+
const appliedFor = (layer: GestureStateLayerName): Record<string, unknown> => {
|
|
165
|
+
const snapshot = applied.get(layer)
|
|
166
|
+
if (snapshot === undefined) {
|
|
167
|
+
throw new Error(
|
|
168
|
+
`gestureStateResolver: active layer '${layer}' has no applied snapshot — ` +
|
|
169
|
+
'activation must record one (internal invariant, r6 minor 3d497c80a16b).',
|
|
170
|
+
)
|
|
171
|
+
}
|
|
172
|
+
return snapshot
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/** Revert `keys` after `layer` released them: each key goes to its fresh destination. */
|
|
176
|
+
const revertKeys = (
|
|
177
|
+
layer: GestureStateLayerName,
|
|
178
|
+
keys: readonly string[],
|
|
179
|
+
): GestureStateRetarget[] => {
|
|
180
|
+
const retargets: GestureStateRetarget[] = []
|
|
181
|
+
for (const key of keys) {
|
|
182
|
+
// A HIGHER active holder keeps the key — the release changes nothing for it.
|
|
183
|
+
const newOwner = owningLayer(key)
|
|
184
|
+
if (newOwner !== null && layerIndex(newOwner) > layerIndex(layer)) continue
|
|
185
|
+
const destination = destinationFor(key)
|
|
186
|
+
if (destination !== null) retargets.push(destination)
|
|
187
|
+
}
|
|
188
|
+
return retargets
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return {
|
|
192
|
+
reconcile() {
|
|
193
|
+
const layers = readLayers()
|
|
194
|
+
const retargets: GestureStateRetarget[] = []
|
|
195
|
+
for (const name of GESTURE_STATE_PRIORITY) {
|
|
196
|
+
if (name === 'animate' || !active.has(name)) continue
|
|
197
|
+
const authoredDefinition = layers[name]
|
|
198
|
+
const appliedTarget = appliedFor(name)
|
|
199
|
+
if (authoredDefinition === undefined) {
|
|
200
|
+
// The layer left the tree while active: full deactivation, bit cleared (no latch).
|
|
201
|
+
active.delete(name)
|
|
202
|
+
applied.delete(name)
|
|
203
|
+
activatedDefinitions.delete(name)
|
|
204
|
+
retargets.push(...revertKeys(name, Object.keys(appliedTarget)))
|
|
205
|
+
continue
|
|
206
|
+
}
|
|
207
|
+
const definition = layerFor(name, layers)!
|
|
208
|
+
const current = definition.target as Record<string, unknown>
|
|
209
|
+
const removed = Object.keys(appliedTarget).filter((key) => !(key in current))
|
|
210
|
+
retargets.push(...revertKeys(name, removed))
|
|
211
|
+
for (const [key, value] of Object.entries(current)) {
|
|
212
|
+
if (key in appliedTarget && appliedTarget[key] === value) continue
|
|
213
|
+
// Added or changed: retarget only if THIS layer owns the key right now.
|
|
214
|
+
if (owningLayer(key) !== name) continue
|
|
215
|
+
retargets.push({ key, value, transition: transitionFor(definition, key) })
|
|
216
|
+
}
|
|
217
|
+
applied.set(name, { ...current })
|
|
218
|
+
}
|
|
219
|
+
return retargets
|
|
220
|
+
},
|
|
221
|
+
heldKeys() {
|
|
222
|
+
const layers = readLayers()
|
|
223
|
+
const held = new Set<string>()
|
|
224
|
+
for (const name of GESTURE_STATE_PRIORITY) {
|
|
225
|
+
if (name === 'animate' || !active.has(name)) continue
|
|
226
|
+
const layer = layerFor(name, layers)
|
|
227
|
+
if (layer === undefined) continue
|
|
228
|
+
for (const key of Object.keys(layer.target)) {
|
|
229
|
+
if (owningLayer(key) === name) held.add(key)
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return held
|
|
233
|
+
},
|
|
234
|
+
reissueActiveTargets() {
|
|
235
|
+
const layers = readLayers()
|
|
236
|
+
const retargets: GestureStateRetarget[] = []
|
|
237
|
+
for (const name of GESTURE_STATE_PRIORITY) {
|
|
238
|
+
if (name === 'animate' || !active.has(name)) continue
|
|
239
|
+
const layer = layerFor(name, layers)
|
|
240
|
+
if (layer === undefined) continue
|
|
241
|
+
for (const key of Object.keys(layer.target)) {
|
|
242
|
+
// Only the OWNING layer re-issues its key — a higher active holder's value wins.
|
|
243
|
+
if (owningLayer(key) !== name) continue
|
|
244
|
+
retargets.push({
|
|
245
|
+
key,
|
|
246
|
+
value: (layer.target as Record<string, unknown>)[key],
|
|
247
|
+
transition: transitionFor(layer, key),
|
|
248
|
+
})
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return retargets
|
|
252
|
+
},
|
|
253
|
+
setActive(layer, isActive) {
|
|
254
|
+
if (layer === 'animate') return [] // the base layer never flips
|
|
255
|
+
if (active.has(layer) === isActive) return [] // idempotent
|
|
256
|
+
if (isActive) {
|
|
257
|
+
const authoredDefinition = readLayers()[layer]
|
|
258
|
+
if (authoredDefinition === undefined) return [] // nothing to overlay; stays inactive
|
|
259
|
+
const definition = authoredDefinition.resolveAtActivation?.() ?? authoredDefinition
|
|
260
|
+
if (authoredDefinition.resolveAtActivation !== undefined) {
|
|
261
|
+
activatedDefinitions.set(layer, definition)
|
|
262
|
+
}
|
|
263
|
+
active.add(layer)
|
|
264
|
+
applied.set(layer, { ...(definition.target as Record<string, unknown>) })
|
|
265
|
+
const retargets: GestureStateRetarget[] = []
|
|
266
|
+
for (const key of Object.keys(definition.target)) {
|
|
267
|
+
// A HIGHER active layer holds the key: the flip changes nothing for it.
|
|
268
|
+
if (owningLayer(key) !== layer) continue
|
|
269
|
+
retargets.push({
|
|
270
|
+
key,
|
|
271
|
+
value: (definition.target as Record<string, unknown>)[key],
|
|
272
|
+
transition: transitionFor(definition, key),
|
|
273
|
+
})
|
|
274
|
+
}
|
|
275
|
+
return retargets
|
|
276
|
+
}
|
|
277
|
+
// Deactivation reverts what was APPLIED (r5 major 2f0ea1c7d3b4) — the live definition
|
|
278
|
+
// may have shrunk or vanished since activation; the applied snapshot is the truth.
|
|
279
|
+
const appliedTarget = appliedFor(layer)
|
|
280
|
+
active.delete(layer)
|
|
281
|
+
applied.delete(layer)
|
|
282
|
+
activatedDefinitions.delete(layer)
|
|
283
|
+
return revertKeys(layer, Object.keys(appliedTarget))
|
|
284
|
+
},
|
|
285
|
+
}
|
|
286
|
+
}
|