@unrulysystems/native-motion-core 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 +9 -0
- package/LICENSE +21 -0
- package/README.md +48 -0
- package/dist/clock.cjs +71 -0
- package/dist/clock.d.cts +23 -0
- package/dist/clock.d.ts +23 -0
- package/dist/clock.js +66 -0
- package/dist/collect-reads.cjs +68 -0
- package/dist/collect-reads.d.cts +23 -0
- package/dist/collect-reads.d.ts +23 -0
- package/dist/collect-reads.js +62 -0
- package/dist/component/boundedArray.cjs +74 -0
- package/dist/component/boundedArray.d.cts +25 -0
- package/dist/component/boundedArray.d.ts +25 -0
- package/dist/component/boundedArray.js +68 -0
- package/dist/component/index.cjs +57 -0
- package/dist/component/index.d.cts +12 -0
- package/dist/component/index.d.ts +12 -0
- package/dist/component/index.js +22 -0
- package/dist/component/orchestration.cjs +129 -0
- package/dist/component/orchestration.d.cts +66 -0
- package/dist/component/orchestration.d.ts +66 -0
- package/dist/component/orchestration.js +124 -0
- package/dist/component/resolve.cjs +104 -0
- package/dist/component/resolve.d.cts +11 -0
- package/dist/component/resolve.d.ts +11 -0
- package/dist/component/resolve.js +97 -0
- package/dist/component/transition.cjs +352 -0
- package/dist/component/transition.d.cts +33 -0
- package/dist/component/transition.d.ts +33 -0
- package/dist/component/transition.js +339 -0
- package/dist/component/types.cjs +114 -0
- package/dist/component/types.d.cts +60 -0
- package/dist/component/types.d.ts +60 -0
- package/dist/component/types.js +111 -0
- package/dist/component/validate.cjs +1015 -0
- package/dist/component/validate.d.cts +37 -0
- package/dist/component/validate.d.ts +37 -0
- package/dist/component/validate.js +1002 -0
- package/dist/component/variants.cjs +333 -0
- package/dist/component/variants.d.cts +106 -0
- package/dist/component/variants.d.ts +106 -0
- package/dist/component/variants.js +321 -0
- package/dist/config/constants.cjs +41 -0
- package/dist/config/constants.d.cts +29 -0
- package/dist/config/constants.d.ts +29 -0
- package/dist/config/constants.js +38 -0
- package/dist/delay.cjs +72 -0
- package/dist/delay.d.cts +26 -0
- package/dist/delay.d.ts +26 -0
- package/dist/delay.js +70 -0
- package/dist/derived.cjs +143 -0
- package/dist/derived.d.cts +41 -0
- package/dist/derived.d.ts +41 -0
- package/dist/derived.js +139 -0
- package/dist/driver/index.cjs +22 -0
- package/dist/driver/index.d.cts +7 -0
- package/dist/driver/index.d.ts +7 -0
- package/dist/driver/index.js +14 -0
- package/dist/driver/keyframeTiming.cjs +130 -0
- package/dist/driver/keyframeTiming.d.cts +18 -0
- package/dist/driver/keyframeTiming.d.ts +18 -0
- package/dist/driver/keyframeTiming.js +124 -0
- package/dist/driver/keyframeTimingConfig.cjs +24 -0
- package/dist/driver/keyframeTimingConfig.d.cts +5 -0
- package/dist/driver/keyframeTimingConfig.d.ts +5 -0
- package/dist/driver/keyframeTimingConfig.js +22 -0
- package/dist/driver/prepare.cjs +459 -0
- package/dist/driver/prepare.d.cts +4 -0
- package/dist/driver/prepare.d.ts +4 -0
- package/dist/driver/prepare.js +454 -0
- package/dist/driver/reference.cjs +762 -0
- package/dist/driver/reference.d.cts +53 -0
- package/dist/driver/reference.d.ts +53 -0
- package/dist/driver/reference.js +757 -0
- package/dist/driver/step.cjs +55 -0
- package/dist/driver/step.d.cts +9 -0
- package/dist/driver/step.d.ts +9 -0
- package/dist/driver/step.js +52 -0
- package/dist/driver/tiers.cjs +40 -0
- package/dist/driver/tiers.d.cts +2 -0
- package/dist/driver/tiers.d.ts +2 -0
- package/dist/driver/tiers.js +37 -0
- package/dist/driver/types.cjs +9 -0
- package/dist/driver/types.d.cts +68 -0
- package/dist/driver/types.d.ts +68 -0
- package/dist/driver/types.js +8 -0
- package/dist/external-animation-ledger.cjs +1250 -0
- package/dist/external-animation-ledger.d.cts +416 -0
- package/dist/external-animation-ledger.d.ts +416 -0
- package/dist/external-animation-ledger.js +1243 -0
- package/dist/gesture/directionLock.cjs +25 -0
- package/dist/gesture/directionLock.d.cts +8 -0
- package/dist/gesture/directionLock.d.ts +8 -0
- package/dist/gesture/directionLock.js +21 -0
- package/dist/gesture/dragConfig.cjs +634 -0
- package/dist/gesture/dragConfig.d.cts +298 -0
- package/dist/gesture/dragConfig.d.ts +298 -0
- package/dist/gesture/dragConfig.js +624 -0
- package/dist/gesture/elastic.cjs +44 -0
- package/dist/gesture/elastic.d.cts +4 -0
- package/dist/gesture/elastic.d.ts +4 -0
- package/dist/gesture/elastic.js +39 -0
- package/dist/gesture/handoffSession.cjs +161 -0
- package/dist/gesture/handoffSession.d.cts +35 -0
- package/dist/gesture/handoffSession.d.ts +35 -0
- package/dist/gesture/handoffSession.js +158 -0
- package/dist/gesture/index.cjs +37 -0
- package/dist/gesture/index.d.cts +12 -0
- package/dist/gesture/index.d.ts +12 -0
- package/dist/gesture/index.js +11 -0
- package/dist/gesture/projection.cjs +95 -0
- package/dist/gesture/projection.d.cts +7 -0
- package/dist/gesture/projection.d.ts +7 -0
- package/dist/gesture/projection.js +87 -0
- package/dist/gesture/session.cjs +162 -0
- package/dist/gesture/session.d.cts +29 -0
- package/dist/gesture/session.d.ts +29 -0
- package/dist/gesture/session.js +158 -0
- package/dist/gesture/types.cjs +5 -0
- package/dist/gesture/types.d.cts +13 -0
- package/dist/gesture/types.d.ts +13 -0
- package/dist/gesture/types.js +4 -0
- package/dist/gesture/viewportConstraints.cjs +38 -0
- package/dist/gesture/viewportConstraints.d.cts +6 -0
- package/dist/gesture/viewportConstraints.d.ts +6 -0
- package/dist/gesture/viewportConstraints.js +34 -0
- package/dist/graph.cjs +226 -0
- package/dist/graph.d.cts +2 -0
- package/dist/graph.d.ts +2 -0
- package/dist/graph.js +223 -0
- package/dist/index.cjs +140 -0
- package/dist/index.d.cts +33 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.js +70 -0
- package/dist/inertia.cjs +214 -0
- package/dist/inertia.d.cts +53 -0
- package/dist/inertia.d.ts +53 -0
- package/dist/inertia.js +212 -0
- package/dist/instant.cjs +66 -0
- package/dist/instant.d.cts +16 -0
- package/dist/instant.d.ts +16 -0
- package/dist/instant.js +63 -0
- package/dist/internal-driver.cjs +81 -0
- package/dist/internal-driver.d.cts +19 -0
- package/dist/internal-driver.d.ts +19 -0
- package/dist/internal-driver.js +35 -0
- package/dist/keyframes.cjs +191 -0
- package/dist/keyframes.d.cts +13 -0
- package/dist/keyframes.d.ts +13 -0
- package/dist/keyframes.js +188 -0
- package/dist/layout/commitDetector.cjs +67 -0
- package/dist/layout/commitDetector.d.cts +21 -0
- package/dist/layout/commitDetector.d.ts +21 -0
- package/dist/layout/commitDetector.js +64 -0
- package/dist/layout/compose.cjs +67 -0
- package/dist/layout/compose.d.cts +30 -0
- package/dist/layout/compose.d.ts +30 -0
- package/dist/layout/compose.js +65 -0
- package/dist/layout/constants.cjs +13 -0
- package/dist/layout/constants.d.cts +6 -0
- package/dist/layout/constants.d.ts +6 -0
- package/dist/layout/constants.js +10 -0
- package/dist/layout/identity.cjs +700 -0
- package/dist/layout/identity.d.cts +67 -0
- package/dist/layout/identity.d.ts +67 -0
- package/dist/layout/identity.js +698 -0
- package/dist/layout/index.cjs +36 -0
- package/dist/layout/index.d.cts +18 -0
- package/dist/layout/index.d.ts +18 -0
- package/dist/layout/index.js +13 -0
- package/dist/layout/measure.cjs +81 -0
- package/dist/layout/measure.d.cts +43 -0
- package/dist/layout/measure.d.ts +43 -0
- package/dist/layout/measure.js +78 -0
- package/dist/layout/projection.cjs +99 -0
- package/dist/layout/projection.d.cts +23 -0
- package/dist/layout/projection.d.ts +23 -0
- package/dist/layout/projection.js +97 -0
- package/dist/layout/scroll.cjs +27 -0
- package/dist/layout/scroll.d.cts +13 -0
- package/dist/layout/scroll.d.ts +13 -0
- package/dist/layout/scroll.js +24 -0
- package/dist/layout/session.cjs +207 -0
- package/dist/layout/session.d.cts +73 -0
- package/dist/layout/session.d.ts +73 -0
- package/dist/layout/session.js +205 -0
- package/dist/layout/tree.cjs +826 -0
- package/dist/layout/tree.d.cts +70 -0
- package/dist/layout/tree.d.ts +70 -0
- package/dist/layout/tree.js +823 -0
- package/dist/layout/types.cjs +36 -0
- package/dist/layout/types.d.cts +31 -0
- package/dist/layout/types.d.ts +31 -0
- package/dist/layout/types.js +35 -0
- package/dist/motion-arc.cjs +184 -0
- package/dist/motion-arc.d.cts +78 -0
- package/dist/motion-arc.d.ts +78 -0
- package/dist/motion-arc.js +183 -0
- package/dist/motion-mix.cjs +205 -0
- package/dist/motion-mix.d.cts +3 -0
- package/dist/motion-mix.d.ts +3 -0
- package/dist/motion-mix.js +202 -0
- package/dist/motion-value-driver-port.cjs +636 -0
- package/dist/motion-value-driver-port.d.cts +406 -0
- package/dist/motion-value-driver-port.d.ts +406 -0
- package/dist/motion-value-driver-port.js +627 -0
- package/dist/motion-value.cjs +189 -0
- package/dist/motion-value.d.cts +51 -0
- package/dist/motion-value.d.ts +51 -0
- package/dist/motion-value.js +185 -0
- package/dist/presence/controller.cjs +657 -0
- package/dist/presence/controller.d.cts +6 -0
- package/dist/presence/controller.d.ts +6 -0
- package/dist/presence/controller.js +652 -0
- package/dist/presence/index.cjs +19 -0
- package/dist/presence/index.d.cts +4 -0
- package/dist/presence/index.d.ts +4 -0
- package/dist/presence/index.js +12 -0
- package/dist/presence/machine.cjs +50 -0
- package/dist/presence/machine.d.cts +10 -0
- package/dist/presence/machine.d.ts +10 -0
- package/dist/presence/machine.js +46 -0
- package/dist/presence/types.cjs +6 -0
- package/dist/presence/types.d.cts +32 -0
- package/dist/presence/types.d.ts +32 -0
- package/dist/presence/types.js +5 -0
- package/dist/repeat.cjs +311 -0
- package/dist/repeat.d.cts +174 -0
- package/dist/repeat.d.ts +174 -0
- package/dist/repeat.js +300 -0
- package/dist/spring.cjs +128 -0
- package/dist/spring.d.cts +18 -0
- package/dist/spring.d.ts +18 -0
- package/dist/spring.js +125 -0
- package/dist/subscriptions.cjs +74 -0
- package/dist/subscriptions.d.cts +19 -0
- package/dist/subscriptions.d.ts +19 -0
- package/dist/subscriptions.js +69 -0
- package/dist/subset/index.cjs +23 -0
- package/dist/subset/index.d.cts +6 -0
- package/dist/subset/index.d.ts +6 -0
- package/dist/subset/index.js +13 -0
- package/dist/subset/normalize.cjs +90 -0
- package/dist/subset/normalize.d.cts +10 -0
- package/dist/subset/normalize.d.ts +10 -0
- package/dist/subset/normalize.js +85 -0
- package/dist/subset/registry.cjs +259 -0
- package/dist/subset/registry.d.cts +25 -0
- package/dist/subset/registry.d.ts +25 -0
- package/dist/subset/registry.js +256 -0
- package/dist/subset/resolve.cjs +98 -0
- package/dist/subset/resolve.d.cts +24 -0
- package/dist/subset/resolve.d.ts +24 -0
- package/dist/subset/resolve.js +90 -0
- package/dist/timing.cjs +206 -0
- package/dist/timing.d.cts +17 -0
- package/dist/timing.d.ts +17 -0
- package/dist/timing.js +201 -0
- package/dist/transformTemplate.cjs +219 -0
- package/dist/transformTemplate.d.cts +29 -0
- package/dist/transformTemplate.d.ts +29 -0
- package/dist/transformTemplate.js +215 -0
- package/dist/transition.cjs +231 -0
- package/dist/transition.d.cts +89 -0
- package/dist/transition.d.ts +89 -0
- package/dist/transition.js +223 -0
- package/dist/types.cjs +4 -0
- package/dist/types.d.cts +175 -0
- package/dist/types.d.ts +175 -0
- package/dist/types.js +3 -0
- package/dist/value-types/color.cjs +220 -0
- package/dist/value-types/color.d.cts +19 -0
- package/dist/value-types/color.d.ts +19 -0
- package/dist/value-types/color.js +218 -0
- package/dist/value-types/complex.cjs +160 -0
- package/dist/value-types/complex.d.cts +19 -0
- package/dist/value-types/complex.d.ts +19 -0
- package/dist/value-types/complex.js +155 -0
- package/dist/value-types/constants.cjs +15 -0
- package/dist/value-types/constants.d.cts +6 -0
- package/dist/value-types/constants.d.ts +6 -0
- package/dist/value-types/constants.js +12 -0
- package/dist/value-types/discrete.cjs +62 -0
- package/dist/value-types/discrete.d.cts +4 -0
- package/dist/value-types/discrete.d.ts +4 -0
- package/dist/value-types/discrete.js +56 -0
- package/dist/value-types/index.cjs +59 -0
- package/dist/value-types/index.d.cts +14 -0
- package/dist/value-types/index.d.ts +14 -0
- package/dist/value-types/index.js +24 -0
- package/dist/value-types/measure-resolve.cjs +325 -0
- package/dist/value-types/measure-resolve.d.cts +91 -0
- package/dist/value-types/measure-resolve.d.ts +91 -0
- package/dist/value-types/measure-resolve.js +313 -0
- package/dist/value-types/mix.cjs +90 -0
- package/dist/value-types/mix.d.cts +27 -0
- package/dist/value-types/mix.d.ts +27 -0
- package/dist/value-types/mix.js +85 -0
- package/dist/value-types/named-colors.cjs +61 -0
- package/dist/value-types/named-colors.d.cts +2 -0
- package/dist/value-types/named-colors.d.ts +2 -0
- package/dist/value-types/named-colors.js +58 -0
- package/dist/value-types/numeric.cjs +86 -0
- package/dist/value-types/numeric.d.cts +16 -0
- package/dist/value-types/numeric.d.ts +16 -0
- package/dist/value-types/numeric.js +79 -0
- package/dist/worklet-layout/config/constants.js +39 -0
- package/dist/worklet-layout/layout/constants.js +11 -0
- package/dist/worklet-layout/layout/identity.js +699 -0
- package/dist/worklet-layout/layout/projection.js +98 -0
- package/dist/worklet-layout/layout/session.js +206 -0
- package/dist/worklet-layout/layout/tree.js +824 -0
- package/dist/worklet-layout/layout/types.js +36 -0
- package/dist/worklet-layout/spring.js +125 -0
- package/dist/worklet-layout/timing.js +201 -0
- package/dist/worklet-layout/transition.js +223 -0
- package/dist/worklet-layout.cjs +47 -0
- package/dist/worklet-layout.d.cts +15 -0
- package/dist/worklet-layout.d.ts +15 -0
- package/dist/worklet-layout.js +28 -0
- package/dist/wrap.cjs +7 -0
- package/dist/wrap.d.cts +1 -0
- package/dist/wrap.d.ts +1 -0
- package/dist/wrap.js +4 -0
- package/package.json +45 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// SPEC-LAYOUT host-agnostic projection engine barrel (REQ-LAYOUT-001). Grows per milestone: M1 pure
|
|
3
|
+
// projection math (here); compose (M2), measure (M3), session (M4) join as they land. Host-agnostic —
|
|
4
|
+
// no react/react-native/reanimated/Fabric/driver import; relative imports only (REQ-CORE-003).
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.accountForLayoutScroll = exports.createCommitDetector = exports.createLayoutIdentityRegistry = exports.createProjectionTree = exports.createProjectionSession = exports.projectMeasured = exports.createMeasureTracker = exports.assertCorrectable = exports.correctRadius = exports.counterScale = exports.composeParentRelative = exports.isIdentity = exports.applyTransformToRect = exports.projectAtProgress = exports.invert = exports.IDENTITY_TRANSFORM = exports.EPSILON_VEL = exports.EPSILON_SCALE = exports.EPSILON_POS = exports.toWindowSpaceRect = void 0;
|
|
7
|
+
var types_1 = require("./types.cjs");
|
|
8
|
+
Object.defineProperty(exports, "toWindowSpaceRect", { enumerable: true, get: function () { return types_1.toWindowSpaceRect; } });
|
|
9
|
+
var constants_1 = require("./constants.cjs");
|
|
10
|
+
Object.defineProperty(exports, "EPSILON_POS", { enumerable: true, get: function () { return constants_1.EPSILON_POS; } });
|
|
11
|
+
Object.defineProperty(exports, "EPSILON_SCALE", { enumerable: true, get: function () { return constants_1.EPSILON_SCALE; } });
|
|
12
|
+
Object.defineProperty(exports, "EPSILON_VEL", { enumerable: true, get: function () { return constants_1.EPSILON_VEL; } });
|
|
13
|
+
var projection_1 = require("./projection.cjs");
|
|
14
|
+
Object.defineProperty(exports, "IDENTITY_TRANSFORM", { enumerable: true, get: function () { return projection_1.IDENTITY_TRANSFORM; } });
|
|
15
|
+
Object.defineProperty(exports, "invert", { enumerable: true, get: function () { return projection_1.invert; } });
|
|
16
|
+
Object.defineProperty(exports, "projectAtProgress", { enumerable: true, get: function () { return projection_1.projectAtProgress; } });
|
|
17
|
+
Object.defineProperty(exports, "applyTransformToRect", { enumerable: true, get: function () { return projection_1.applyTransformToRect; } });
|
|
18
|
+
Object.defineProperty(exports, "isIdentity", { enumerable: true, get: function () { return projection_1.isIdentity; } });
|
|
19
|
+
var compose_1 = require("./compose.cjs");
|
|
20
|
+
Object.defineProperty(exports, "composeParentRelative", { enumerable: true, get: function () { return compose_1.composeParentRelative; } });
|
|
21
|
+
Object.defineProperty(exports, "counterScale", { enumerable: true, get: function () { return compose_1.counterScale; } });
|
|
22
|
+
Object.defineProperty(exports, "correctRadius", { enumerable: true, get: function () { return compose_1.correctRadius; } });
|
|
23
|
+
Object.defineProperty(exports, "assertCorrectable", { enumerable: true, get: function () { return compose_1.assertCorrectable; } });
|
|
24
|
+
var measure_1 = require("./measure.cjs");
|
|
25
|
+
Object.defineProperty(exports, "createMeasureTracker", { enumerable: true, get: function () { return measure_1.createMeasureTracker; } });
|
|
26
|
+
Object.defineProperty(exports, "projectMeasured", { enumerable: true, get: function () { return measure_1.projectMeasured; } });
|
|
27
|
+
var session_1 = require("./session.cjs");
|
|
28
|
+
Object.defineProperty(exports, "createProjectionSession", { enumerable: true, get: function () { return session_1.createProjectionSession; } });
|
|
29
|
+
var tree_1 = require("./tree.cjs");
|
|
30
|
+
Object.defineProperty(exports, "createProjectionTree", { enumerable: true, get: function () { return tree_1.createProjectionTree; } });
|
|
31
|
+
var identity_1 = require("./identity.cjs");
|
|
32
|
+
Object.defineProperty(exports, "createLayoutIdentityRegistry", { enumerable: true, get: function () { return identity_1.createLayoutIdentityRegistry; } });
|
|
33
|
+
var commitDetector_1 = require("./commitDetector.cjs");
|
|
34
|
+
Object.defineProperty(exports, "createCommitDetector", { enumerable: true, get: function () { return commitDetector_1.createCommitDetector; } });
|
|
35
|
+
var scroll_1 = require("./scroll.cjs");
|
|
36
|
+
Object.defineProperty(exports, "accountForLayoutScroll", { enumerable: true, get: function () { return scroll_1.accountForLayoutScroll; } });
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type { Rect, Transform, LayoutIdToken, WindowSpaceRect } from "./types.cjs";
|
|
2
|
+
export { toWindowSpaceRect } from "./types.cjs";
|
|
3
|
+
export { EPSILON_POS, EPSILON_SCALE, EPSILON_VEL } from "./constants.cjs";
|
|
4
|
+
export { IDENTITY_TRANSFORM, invert, projectAtProgress, applyTransformToRect, isIdentity, } from "./projection.cjs";
|
|
5
|
+
export type { CorrectedRadius } from "./compose.cjs";
|
|
6
|
+
export { composeParentRelative, counterScale, correctRadius, assertCorrectable } from "./compose.cjs";
|
|
7
|
+
export type { MeasureState, MeasureAdapter, Measurement, MeasureTracker } from "./measure.cjs";
|
|
8
|
+
export { createMeasureTracker, projectMeasured } from "./measure.cjs";
|
|
9
|
+
export type { ProjectionSession, ProjectionSessionOptions, ProjectionSessionState, RectVelocity, } from "./session.cjs";
|
|
10
|
+
export { createProjectionSession } from "./session.cjs";
|
|
11
|
+
export type { ProjectionNodeOutput, ProjectionStaleNodeCode, ProjectionStaleNodeReport, ProjectionTree, ProjectionTreeNode, ProjectionTreeOptions, } from "./tree.cjs";
|
|
12
|
+
export { createProjectionTree } from "./tree.cjs";
|
|
13
|
+
export type { IdentityEnterResult, IdentityHolderHandle, IdentityRead, LayoutIdentityFlightOptions, LayoutIdentityRegistry, LayoutIdentityRegistryOptions, LayoutIdentityRole, } from "./identity.cjs";
|
|
14
|
+
export { createLayoutIdentityRegistry } from "./identity.cjs";
|
|
15
|
+
export type { CommitDetection, CommitDetector } from "./commitDetector.cjs";
|
|
16
|
+
export { createCommitDetector } from "./commitDetector.cjs";
|
|
17
|
+
export type { LayoutScrollOffset } from "./scroll.cjs";
|
|
18
|
+
export { accountForLayoutScroll } from "./scroll.cjs";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type { Rect, Transform, LayoutIdToken, WindowSpaceRect } from "./types.js";
|
|
2
|
+
export { toWindowSpaceRect } from "./types.js";
|
|
3
|
+
export { EPSILON_POS, EPSILON_SCALE, EPSILON_VEL } from "./constants.js";
|
|
4
|
+
export { IDENTITY_TRANSFORM, invert, projectAtProgress, applyTransformToRect, isIdentity, } from "./projection.js";
|
|
5
|
+
export type { CorrectedRadius } from "./compose.js";
|
|
6
|
+
export { composeParentRelative, counterScale, correctRadius, assertCorrectable } from "./compose.js";
|
|
7
|
+
export type { MeasureState, MeasureAdapter, Measurement, MeasureTracker } from "./measure.js";
|
|
8
|
+
export { createMeasureTracker, projectMeasured } from "./measure.js";
|
|
9
|
+
export type { ProjectionSession, ProjectionSessionOptions, ProjectionSessionState, RectVelocity, } from "./session.js";
|
|
10
|
+
export { createProjectionSession } from "./session.js";
|
|
11
|
+
export type { ProjectionNodeOutput, ProjectionStaleNodeCode, ProjectionStaleNodeReport, ProjectionTree, ProjectionTreeNode, ProjectionTreeOptions, } from "./tree.js";
|
|
12
|
+
export { createProjectionTree } from "./tree.js";
|
|
13
|
+
export type { IdentityEnterResult, IdentityHolderHandle, IdentityRead, LayoutIdentityFlightOptions, LayoutIdentityRegistry, LayoutIdentityRegistryOptions, LayoutIdentityRole, } from "./identity.js";
|
|
14
|
+
export { createLayoutIdentityRegistry } from "./identity.js";
|
|
15
|
+
export type { CommitDetection, CommitDetector } from "./commitDetector.js";
|
|
16
|
+
export { createCommitDetector } from "./commitDetector.js";
|
|
17
|
+
export type { LayoutScrollOffset } from "./scroll.js";
|
|
18
|
+
export { accountForLayoutScroll } from "./scroll.js";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// SPEC-LAYOUT host-agnostic projection engine barrel (REQ-LAYOUT-001). Grows per milestone: M1 pure
|
|
2
|
+
// projection math (here); compose (M2), measure (M3), session (M4) join as they land. Host-agnostic —
|
|
3
|
+
// no react/react-native/reanimated/Fabric/driver import; relative imports only (REQ-CORE-003).
|
|
4
|
+
export { toWindowSpaceRect } from "./types.js";
|
|
5
|
+
export { EPSILON_POS, EPSILON_SCALE, EPSILON_VEL } from "./constants.js";
|
|
6
|
+
export { IDENTITY_TRANSFORM, invert, projectAtProgress, applyTransformToRect, isIdentity, } from "./projection.js";
|
|
7
|
+
export { composeParentRelative, counterScale, correctRadius, assertCorrectable } from "./compose.js";
|
|
8
|
+
export { createMeasureTracker, projectMeasured } from "./measure.js";
|
|
9
|
+
export { createProjectionSession } from "./session.js";
|
|
10
|
+
export { createProjectionTree } from "./tree.js";
|
|
11
|
+
export { createLayoutIdentityRegistry } from "./identity.js";
|
|
12
|
+
export { createCommitDetector } from "./commitDetector.js";
|
|
13
|
+
export { accountForLayoutScroll } from "./scroll.js";
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// SPEC-LAYOUT §2/§4a — the measurement lifecycle + fail-closed contract (REQ-LAYOUT-010/011/016/017/019).
|
|
3
|
+
// `null` is a first-class state, never an error to swallow and never a value to assume: an unmeasured read
|
|
4
|
+
// yields an identity transform + unsettled and is retried next epoch. A read fires only after the attached-
|
|
5
|
+
// and-laid-out signal; a view is measured at most once per epoch and the result is cached (the per-frame
|
|
6
|
+
// projection recomputes from the cache, never re-measures); identity is re-validated against a stable token
|
|
7
|
+
// before applying, failing closed on a recycled/unmounted tag. Host-agnostic: the measurement primitive is
|
|
8
|
+
// an injected adapter (a fake host at M1, Fabric measure at M2); `core` never imports a host measure API.
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.createMeasureTracker = createMeasureTracker;
|
|
11
|
+
exports.projectMeasured = projectMeasured;
|
|
12
|
+
const projection_1 = require("./projection.cjs");
|
|
13
|
+
function createMeasureTracker(token) {
|
|
14
|
+
let state = 'unattached';
|
|
15
|
+
let epoch = Number.NaN; // no epoch opened yet; the first beginEpoch always invalidates
|
|
16
|
+
let attemptedThisEpoch = false; // the adapter was read this epoch (once-per-epoch guard, incl. a null read)
|
|
17
|
+
let cachedRect = null;
|
|
18
|
+
let measured = false;
|
|
19
|
+
function current() {
|
|
20
|
+
return { state, measured, settled: measured, rect: cachedRect };
|
|
21
|
+
}
|
|
22
|
+
function resetMeasurement() {
|
|
23
|
+
measured = false;
|
|
24
|
+
cachedRect = null;
|
|
25
|
+
if (state === 'measured')
|
|
26
|
+
state = 'attached';
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
token,
|
|
30
|
+
attach() {
|
|
31
|
+
if (state === 'unattached')
|
|
32
|
+
state = 'attached';
|
|
33
|
+
},
|
|
34
|
+
beginEpoch(e) {
|
|
35
|
+
// Object.is so re-opening the same epoch is a no-op but the initial NaN epoch always invalidates.
|
|
36
|
+
if (!Object.is(e, epoch)) {
|
|
37
|
+
epoch = e;
|
|
38
|
+
attemptedThisEpoch = false;
|
|
39
|
+
resetMeasurement();
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
measure(adapter) {
|
|
43
|
+
// Never read before the attached-and-laid-out signal (REQ-LAYOUT-010).
|
|
44
|
+
if (state === 'unattached')
|
|
45
|
+
return current();
|
|
46
|
+
// Once-per-epoch: the adapter is read at most once; the per-frame path reads the cache (REQ-LAYOUT-017).
|
|
47
|
+
if (attemptedThisEpoch)
|
|
48
|
+
return current();
|
|
49
|
+
attemptedThisEpoch = true;
|
|
50
|
+
const rect = adapter.measure(token);
|
|
51
|
+
if (rect === null) {
|
|
52
|
+
// Fail-closed: a null read stays unmeasured/identity and is retried next epoch — never a garbage
|
|
53
|
+
// delta, never swallowed (REQ-LAYOUT-011). The null branch is explicit.
|
|
54
|
+
resetMeasurement();
|
|
55
|
+
return current();
|
|
56
|
+
}
|
|
57
|
+
measured = true;
|
|
58
|
+
cachedRect = rect;
|
|
59
|
+
state = 'measured';
|
|
60
|
+
return current();
|
|
61
|
+
},
|
|
62
|
+
validate(liveToken) {
|
|
63
|
+
if (liveToken === token)
|
|
64
|
+
return true;
|
|
65
|
+
// Stale identity (Fabric recycled the tag / the view unmounted): the cached rect no longer describes the
|
|
66
|
+
// live view. Fail closed and re-enter the measure loop rather than applying a stale delta (REQ-LAYOUT-016).
|
|
67
|
+
resetMeasurement();
|
|
68
|
+
return false;
|
|
69
|
+
},
|
|
70
|
+
current,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The fail-closed projection bridge (REQ-LAYOUT-011): if EITHER the before or after read is null (unmeasured),
|
|
75
|
+
* emit an identity transform — no motion, no garbage delta — else the real FLIP projection at `progress`.
|
|
76
|
+
*/
|
|
77
|
+
function projectMeasured(before, after, progress) {
|
|
78
|
+
if (before === null || after === null)
|
|
79
|
+
return projection_1.IDENTITY_TRANSFORM;
|
|
80
|
+
return (0, projection_1.projectAtProgress)(before, after, progress);
|
|
81
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { LayoutIdToken, Rect, Transform } from "./types.cjs";
|
|
2
|
+
export type MeasureState = 'unattached' | 'attached' | 'measured';
|
|
3
|
+
/**
|
|
4
|
+
* The host measurement primitive, injected. Returns the element's current rect, or `null` when it cannot be
|
|
5
|
+
* measured (unattached / off-screen). A fake adapter at M1; the Fabric `measure` adapter at M2.
|
|
6
|
+
*/
|
|
7
|
+
export interface MeasureAdapter {
|
|
8
|
+
measure(token: LayoutIdToken): Rect | null;
|
|
9
|
+
}
|
|
10
|
+
/** The resolved measurement of one element for the current epoch. */
|
|
11
|
+
export interface Measurement {
|
|
12
|
+
readonly state: MeasureState;
|
|
13
|
+
/** A non-null read landed this epoch. */
|
|
14
|
+
readonly measured: boolean;
|
|
15
|
+
/** Measurement-availability = settle: an unmeasured element is unsettled (REQ-LAYOUT-019). */
|
|
16
|
+
readonly settled: boolean;
|
|
17
|
+
/** The cached measured rect, or `null` while unmeasured (fail-closed, never a garbage delta). */
|
|
18
|
+
readonly rect: Rect | null;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* A per-element measurement tracker bound to a stable identity token (REQ-LAYOUT-016). Enforces read-after-
|
|
22
|
+
* attach (REQ-LAYOUT-010), measure-once-per-epoch caching (REQ-LAYOUT-017), and null-fails-closed
|
|
23
|
+
* (REQ-LAYOUT-011). Stateful; not thread-shared.
|
|
24
|
+
*/
|
|
25
|
+
export interface MeasureTracker {
|
|
26
|
+
readonly token: LayoutIdToken;
|
|
27
|
+
/** The attached-and-laid-out signal; enables reads (REQ-LAYOUT-010). */
|
|
28
|
+
attach(): void;
|
|
29
|
+
/** Open a layout epoch; a new epoch invalidates the cache and re-opens measurement (REQ-LAYOUT-017). */
|
|
30
|
+
beginEpoch(epoch: number): void;
|
|
31
|
+
/** Measure at most once per epoch via the adapter, caching the result. Null fails closed (REQ-LAYOUT-011). */
|
|
32
|
+
measure(adapter: MeasureAdapter): Measurement;
|
|
33
|
+
/** Re-validate the live identity token before applying; a mismatch fails closed (REQ-LAYOUT-016). */
|
|
34
|
+
validate(liveToken: LayoutIdToken): boolean;
|
|
35
|
+
/** The current cached measurement without re-reading. */
|
|
36
|
+
current(): Measurement;
|
|
37
|
+
}
|
|
38
|
+
export declare function createMeasureTracker(token: LayoutIdToken): MeasureTracker;
|
|
39
|
+
/**
|
|
40
|
+
* The fail-closed projection bridge (REQ-LAYOUT-011): if EITHER the before or after read is null (unmeasured),
|
|
41
|
+
* emit an identity transform — no motion, no garbage delta — else the real FLIP projection at `progress`.
|
|
42
|
+
*/
|
|
43
|
+
export declare function projectMeasured(before: Rect | null, after: Rect | null, progress: number): Transform;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { LayoutIdToken, Rect, Transform } from "./types.js";
|
|
2
|
+
export type MeasureState = 'unattached' | 'attached' | 'measured';
|
|
3
|
+
/**
|
|
4
|
+
* The host measurement primitive, injected. Returns the element's current rect, or `null` when it cannot be
|
|
5
|
+
* measured (unattached / off-screen). A fake adapter at M1; the Fabric `measure` adapter at M2.
|
|
6
|
+
*/
|
|
7
|
+
export interface MeasureAdapter {
|
|
8
|
+
measure(token: LayoutIdToken): Rect | null;
|
|
9
|
+
}
|
|
10
|
+
/** The resolved measurement of one element for the current epoch. */
|
|
11
|
+
export interface Measurement {
|
|
12
|
+
readonly state: MeasureState;
|
|
13
|
+
/** A non-null read landed this epoch. */
|
|
14
|
+
readonly measured: boolean;
|
|
15
|
+
/** Measurement-availability = settle: an unmeasured element is unsettled (REQ-LAYOUT-019). */
|
|
16
|
+
readonly settled: boolean;
|
|
17
|
+
/** The cached measured rect, or `null` while unmeasured (fail-closed, never a garbage delta). */
|
|
18
|
+
readonly rect: Rect | null;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* A per-element measurement tracker bound to a stable identity token (REQ-LAYOUT-016). Enforces read-after-
|
|
22
|
+
* attach (REQ-LAYOUT-010), measure-once-per-epoch caching (REQ-LAYOUT-017), and null-fails-closed
|
|
23
|
+
* (REQ-LAYOUT-011). Stateful; not thread-shared.
|
|
24
|
+
*/
|
|
25
|
+
export interface MeasureTracker {
|
|
26
|
+
readonly token: LayoutIdToken;
|
|
27
|
+
/** The attached-and-laid-out signal; enables reads (REQ-LAYOUT-010). */
|
|
28
|
+
attach(): void;
|
|
29
|
+
/** Open a layout epoch; a new epoch invalidates the cache and re-opens measurement (REQ-LAYOUT-017). */
|
|
30
|
+
beginEpoch(epoch: number): void;
|
|
31
|
+
/** Measure at most once per epoch via the adapter, caching the result. Null fails closed (REQ-LAYOUT-011). */
|
|
32
|
+
measure(adapter: MeasureAdapter): Measurement;
|
|
33
|
+
/** Re-validate the live identity token before applying; a mismatch fails closed (REQ-LAYOUT-016). */
|
|
34
|
+
validate(liveToken: LayoutIdToken): boolean;
|
|
35
|
+
/** The current cached measurement without re-reading. */
|
|
36
|
+
current(): Measurement;
|
|
37
|
+
}
|
|
38
|
+
export declare function createMeasureTracker(token: LayoutIdToken): MeasureTracker;
|
|
39
|
+
/**
|
|
40
|
+
* The fail-closed projection bridge (REQ-LAYOUT-011): if EITHER the before or after read is null (unmeasured),
|
|
41
|
+
* emit an identity transform — no motion, no garbage delta — else the real FLIP projection at `progress`.
|
|
42
|
+
*/
|
|
43
|
+
export declare function projectMeasured(before: Rect | null, after: Rect | null, progress: number): Transform;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// SPEC-LAYOUT §2/§4a — the measurement lifecycle + fail-closed contract (REQ-LAYOUT-010/011/016/017/019).
|
|
2
|
+
// `null` is a first-class state, never an error to swallow and never a value to assume: an unmeasured read
|
|
3
|
+
// yields an identity transform + unsettled and is retried next epoch. A read fires only after the attached-
|
|
4
|
+
// and-laid-out signal; a view is measured at most once per epoch and the result is cached (the per-frame
|
|
5
|
+
// projection recomputes from the cache, never re-measures); identity is re-validated against a stable token
|
|
6
|
+
// before applying, failing closed on a recycled/unmounted tag. Host-agnostic: the measurement primitive is
|
|
7
|
+
// an injected adapter (a fake host at M1, Fabric measure at M2); `core` never imports a host measure API.
|
|
8
|
+
import { IDENTITY_TRANSFORM, projectAtProgress } from "./projection.js";
|
|
9
|
+
export function createMeasureTracker(token) {
|
|
10
|
+
let state = 'unattached';
|
|
11
|
+
let epoch = Number.NaN; // no epoch opened yet; the first beginEpoch always invalidates
|
|
12
|
+
let attemptedThisEpoch = false; // the adapter was read this epoch (once-per-epoch guard, incl. a null read)
|
|
13
|
+
let cachedRect = null;
|
|
14
|
+
let measured = false;
|
|
15
|
+
function current() {
|
|
16
|
+
return { state, measured, settled: measured, rect: cachedRect };
|
|
17
|
+
}
|
|
18
|
+
function resetMeasurement() {
|
|
19
|
+
measured = false;
|
|
20
|
+
cachedRect = null;
|
|
21
|
+
if (state === 'measured')
|
|
22
|
+
state = 'attached';
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
token,
|
|
26
|
+
attach() {
|
|
27
|
+
if (state === 'unattached')
|
|
28
|
+
state = 'attached';
|
|
29
|
+
},
|
|
30
|
+
beginEpoch(e) {
|
|
31
|
+
// Object.is so re-opening the same epoch is a no-op but the initial NaN epoch always invalidates.
|
|
32
|
+
if (!Object.is(e, epoch)) {
|
|
33
|
+
epoch = e;
|
|
34
|
+
attemptedThisEpoch = false;
|
|
35
|
+
resetMeasurement();
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
measure(adapter) {
|
|
39
|
+
// Never read before the attached-and-laid-out signal (REQ-LAYOUT-010).
|
|
40
|
+
if (state === 'unattached')
|
|
41
|
+
return current();
|
|
42
|
+
// Once-per-epoch: the adapter is read at most once; the per-frame path reads the cache (REQ-LAYOUT-017).
|
|
43
|
+
if (attemptedThisEpoch)
|
|
44
|
+
return current();
|
|
45
|
+
attemptedThisEpoch = true;
|
|
46
|
+
const rect = adapter.measure(token);
|
|
47
|
+
if (rect === null) {
|
|
48
|
+
// Fail-closed: a null read stays unmeasured/identity and is retried next epoch — never a garbage
|
|
49
|
+
// delta, never swallowed (REQ-LAYOUT-011). The null branch is explicit.
|
|
50
|
+
resetMeasurement();
|
|
51
|
+
return current();
|
|
52
|
+
}
|
|
53
|
+
measured = true;
|
|
54
|
+
cachedRect = rect;
|
|
55
|
+
state = 'measured';
|
|
56
|
+
return current();
|
|
57
|
+
},
|
|
58
|
+
validate(liveToken) {
|
|
59
|
+
if (liveToken === token)
|
|
60
|
+
return true;
|
|
61
|
+
// Stale identity (Fabric recycled the tag / the view unmounted): the cached rect no longer describes the
|
|
62
|
+
// live view. Fail closed and re-enter the measure loop rather than applying a stale delta (REQ-LAYOUT-016).
|
|
63
|
+
resetMeasurement();
|
|
64
|
+
return false;
|
|
65
|
+
},
|
|
66
|
+
current,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The fail-closed projection bridge (REQ-LAYOUT-011): if EITHER the before or after read is null (unmeasured),
|
|
71
|
+
* emit an identity transform — no motion, no garbage delta — else the real FLIP projection at `progress`.
|
|
72
|
+
*/
|
|
73
|
+
export function projectMeasured(before, after, progress) {
|
|
74
|
+
'worklet';
|
|
75
|
+
if (before === null || after === null)
|
|
76
|
+
return IDENTITY_TRANSFORM;
|
|
77
|
+
return projectAtProgress(before, after, progress);
|
|
78
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// @frame-path — executes inside the UI-runtime frame step; allocation-gated (REQ-DRIVER-021).
|
|
3
|
+
// SPEC-LAYOUT §2/§4a — the pure FLIP projection math (REQ-LAYOUT-002/011). Given a `before` rect (where the
|
|
4
|
+
// element was) and an `after` rect (where the host layout engine just placed it), `invert` yields the
|
|
5
|
+
// transform-only correction that makes the element — already laid out at `after` — appear at `before`.
|
|
6
|
+
// Driving progress 0→1 lerps that correction to identity, so at settle the element is coincident with the
|
|
7
|
+
// host layout and the applied transform is identity (Motion keeps layout authority; we animate the
|
|
8
|
+
// transition only). Host-agnostic, no graph/clock — the progress itself is driven by the reused SPRING in
|
|
9
|
+
// the session (M4). All transforms are about the rect's TOP-LEFT origin (transformOrigin 0,0), which keeps
|
|
10
|
+
// the invert/apply algebra exact and composable; a center/other origin is an M2 parity refinement (§7).
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.IDENTITY_TRANSFORM = void 0;
|
|
13
|
+
exports.invert = invert;
|
|
14
|
+
exports.projectAtProgress = projectAtProgress;
|
|
15
|
+
exports.applyTransformToRect = applyTransformToRect;
|
|
16
|
+
exports.isIdentity = isIdentity;
|
|
17
|
+
const constants_1 = require("./constants.cjs");
|
|
18
|
+
/** The no-op correction: element sits exactly on its host layout. */
|
|
19
|
+
exports.IDENTITY_TRANSFORM = {
|
|
20
|
+
translateX: 0,
|
|
21
|
+
translateY: 0,
|
|
22
|
+
scaleX: 1,
|
|
23
|
+
scaleY: 1,
|
|
24
|
+
};
|
|
25
|
+
// Linear interpolation of a single transform scalar by the (spring-driven) progress. Deliberately a scalar
|
|
26
|
+
// lerp, NOT value-types `mixNumeric` — that wraps a NumericValue for typed style interpolation, which is
|
|
27
|
+
// overkill for a raw geometric component. The reused SPRING supplies `progress`; this only shapes it.
|
|
28
|
+
function lerp(from, to, progress) {
|
|
29
|
+
return from + (to - from) * progress;
|
|
30
|
+
}
|
|
31
|
+
function assertMeasurable(rect) {
|
|
32
|
+
// A zero/negative/non-finite dimension would divide-by-zero (or NaN) the scale — fail loud, never fabricate
|
|
33
|
+
// a garbage delta (REQ-LAYOUT-011). Position may be any finite number; only the dimensions must be > 0.
|
|
34
|
+
if (!Number.isFinite(rect.width) ||
|
|
35
|
+
!Number.isFinite(rect.height) ||
|
|
36
|
+
rect.width <= 0 ||
|
|
37
|
+
rect.height <= 0) {
|
|
38
|
+
// ui-throw-ok: unreachable from the UI path — tree.setProjection validates BOTH rects
|
|
39
|
+
// (finite fields; positive target dimensions) before calling projectAtProgress (seal r11,
|
|
40
|
+
// F2a), so this assert cannot fire from the UI-reachable set. invert's remaining callers are
|
|
41
|
+
// JS-thread (session transform, web engine, verification), where the REQ-LAYOUT-011
|
|
42
|
+
// fail-loud contract stands.
|
|
43
|
+
throw new Error(`layout: cannot project onto a rect with non-positive/non-finite dimensions (measure returned width=${rect.width}, height=${rect.height})`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The FLIP invert (REQ-LAYOUT-002): the transform that makes an element currently laid out at `after` appear
|
|
48
|
+
* at `before`. Scaling is about the top-left origin, so the top-left stays put under scale and the translate
|
|
49
|
+
* is the raw origin delta. `applyTransformToRect(invert(b, a), a)` reproduces `b` exactly.
|
|
50
|
+
*/
|
|
51
|
+
// alloc-ok: js-thread — record-building API for JS-side callers (session.transform, web engine,
|
|
52
|
+
// verification); the UI frame path inverts field-wise inside the registry's readInto.
|
|
53
|
+
function invert(before, after) {
|
|
54
|
+
assertMeasurable(after);
|
|
55
|
+
return {
|
|
56
|
+
translateX: before.x - after.x,
|
|
57
|
+
translateY: before.y - after.y,
|
|
58
|
+
scaleX: before.width / after.width,
|
|
59
|
+
scaleY: before.height / after.height,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* The projection correction at animation progress `p` (REQ-LAYOUT-002/017): lerp each component from the
|
|
64
|
+
* invert at `p=0` (element at `before`) to identity at `p=1` (element on the host layout). Recomputed from
|
|
65
|
+
* the cached before/after and the current progress — never by re-measuring.
|
|
66
|
+
*/
|
|
67
|
+
// alloc-ok: js-thread — record-building API for JS-side callers and verification; not on the UI
|
|
68
|
+
// frame path (readInto owns the per-frame projection math).
|
|
69
|
+
function projectAtProgress(before, after, progress) {
|
|
70
|
+
const from = invert(before, after);
|
|
71
|
+
return {
|
|
72
|
+
translateX: lerp(from.translateX, exports.IDENTITY_TRANSFORM.translateX, progress),
|
|
73
|
+
translateY: lerp(from.translateY, exports.IDENTITY_TRANSFORM.translateY, progress),
|
|
74
|
+
scaleX: lerp(from.scaleX, exports.IDENTITY_TRANSFORM.scaleX, progress),
|
|
75
|
+
scaleY: lerp(from.scaleY, exports.IDENTITY_TRANSFORM.scaleY, progress),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Apply a transform (translate + scale about the rect's top-left) to a rect, yielding the visual rect. Used
|
|
80
|
+
* for assertions and for the retarget seam's `currentVisual` (M4). Translate is in the unscaled frame; size
|
|
81
|
+
* scales in place.
|
|
82
|
+
*/
|
|
83
|
+
// alloc-ok: js-thread — record-building API for assertions and the retarget seam's JS-side
|
|
84
|
+
// currentVisual; not on the UI frame path.
|
|
85
|
+
function applyTransformToRect(t, rect) {
|
|
86
|
+
return {
|
|
87
|
+
x: rect.x + t.translateX,
|
|
88
|
+
y: rect.y + t.translateY,
|
|
89
|
+
width: rect.width * t.scaleX,
|
|
90
|
+
height: rect.height * t.scaleY,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/** Whether a transform is within the settle epsilons of identity (translate ≤ pos eps, scale ≤ scale eps). */
|
|
94
|
+
function isIdentity(t, epsPos = constants_1.EPSILON_POS, epsScale = constants_1.EPSILON_SCALE) {
|
|
95
|
+
return (Math.abs(t.translateX) < epsPos &&
|
|
96
|
+
Math.abs(t.translateY) < epsPos &&
|
|
97
|
+
Math.abs(t.scaleX - 1) < epsScale &&
|
|
98
|
+
Math.abs(t.scaleY - 1) < epsScale);
|
|
99
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Rect, Transform } from "./types.cjs";
|
|
2
|
+
/** The no-op correction: element sits exactly on its host layout. */
|
|
3
|
+
export declare const IDENTITY_TRANSFORM: Transform;
|
|
4
|
+
/**
|
|
5
|
+
* The FLIP invert (REQ-LAYOUT-002): the transform that makes an element currently laid out at `after` appear
|
|
6
|
+
* at `before`. Scaling is about the top-left origin, so the top-left stays put under scale and the translate
|
|
7
|
+
* is the raw origin delta. `applyTransformToRect(invert(b, a), a)` reproduces `b` exactly.
|
|
8
|
+
*/
|
|
9
|
+
export declare function invert(before: Rect, after: Rect): Transform;
|
|
10
|
+
/**
|
|
11
|
+
* The projection correction at animation progress `p` (REQ-LAYOUT-002/017): lerp each component from the
|
|
12
|
+
* invert at `p=0` (element at `before`) to identity at `p=1` (element on the host layout). Recomputed from
|
|
13
|
+
* the cached before/after and the current progress — never by re-measuring.
|
|
14
|
+
*/
|
|
15
|
+
export declare function projectAtProgress(before: Rect, after: Rect, progress: number): Transform;
|
|
16
|
+
/**
|
|
17
|
+
* Apply a transform (translate + scale about the rect's top-left) to a rect, yielding the visual rect. Used
|
|
18
|
+
* for assertions and for the retarget seam's `currentVisual` (M4). Translate is in the unscaled frame; size
|
|
19
|
+
* scales in place.
|
|
20
|
+
*/
|
|
21
|
+
export declare function applyTransformToRect(t: Transform, rect: Rect): Rect;
|
|
22
|
+
/** Whether a transform is within the settle epsilons of identity (translate ≤ pos eps, scale ≤ scale eps). */
|
|
23
|
+
export declare function isIdentity(t: Transform, epsPos?: number, epsScale?: number): boolean;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Rect, Transform } from "./types.js";
|
|
2
|
+
/** The no-op correction: element sits exactly on its host layout. */
|
|
3
|
+
export declare const IDENTITY_TRANSFORM: Transform;
|
|
4
|
+
/**
|
|
5
|
+
* The FLIP invert (REQ-LAYOUT-002): the transform that makes an element currently laid out at `after` appear
|
|
6
|
+
* at `before`. Scaling is about the top-left origin, so the top-left stays put under scale and the translate
|
|
7
|
+
* is the raw origin delta. `applyTransformToRect(invert(b, a), a)` reproduces `b` exactly.
|
|
8
|
+
*/
|
|
9
|
+
export declare function invert(before: Rect, after: Rect): Transform;
|
|
10
|
+
/**
|
|
11
|
+
* The projection correction at animation progress `p` (REQ-LAYOUT-002/017): lerp each component from the
|
|
12
|
+
* invert at `p=0` (element at `before`) to identity at `p=1` (element on the host layout). Recomputed from
|
|
13
|
+
* the cached before/after and the current progress — never by re-measuring.
|
|
14
|
+
*/
|
|
15
|
+
export declare function projectAtProgress(before: Rect, after: Rect, progress: number): Transform;
|
|
16
|
+
/**
|
|
17
|
+
* Apply a transform (translate + scale about the rect's top-left) to a rect, yielding the visual rect. Used
|
|
18
|
+
* for assertions and for the retarget seam's `currentVisual` (M4). Translate is in the unscaled frame; size
|
|
19
|
+
* scales in place.
|
|
20
|
+
*/
|
|
21
|
+
export declare function applyTransformToRect(t: Transform, rect: Rect): Rect;
|
|
22
|
+
/** Whether a transform is within the settle epsilons of identity (translate ≤ pos eps, scale ≤ scale eps). */
|
|
23
|
+
export declare function isIdentity(t: Transform, epsPos?: number, epsScale?: number): boolean;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// @frame-path — executes inside the UI-runtime frame step; allocation-gated (REQ-DRIVER-021).
|
|
2
|
+
// SPEC-LAYOUT §2/§4a — the pure FLIP projection math (REQ-LAYOUT-002/011). Given a `before` rect (where the
|
|
3
|
+
// element was) and an `after` rect (where the host layout engine just placed it), `invert` yields the
|
|
4
|
+
// transform-only correction that makes the element — already laid out at `after` — appear at `before`.
|
|
5
|
+
// Driving progress 0→1 lerps that correction to identity, so at settle the element is coincident with the
|
|
6
|
+
// host layout and the applied transform is identity (Motion keeps layout authority; we animate the
|
|
7
|
+
// transition only). Host-agnostic, no graph/clock — the progress itself is driven by the reused SPRING in
|
|
8
|
+
// the session (M4). All transforms are about the rect's TOP-LEFT origin (transformOrigin 0,0), which keeps
|
|
9
|
+
// the invert/apply algebra exact and composable; a center/other origin is an M2 parity refinement (§7).
|
|
10
|
+
import { EPSILON_POS, EPSILON_SCALE } from "./constants.js";
|
|
11
|
+
/** The no-op correction: element sits exactly on its host layout. */
|
|
12
|
+
export const IDENTITY_TRANSFORM = {
|
|
13
|
+
translateX: 0,
|
|
14
|
+
translateY: 0,
|
|
15
|
+
scaleX: 1,
|
|
16
|
+
scaleY: 1,
|
|
17
|
+
};
|
|
18
|
+
// Linear interpolation of a single transform scalar by the (spring-driven) progress. Deliberately a scalar
|
|
19
|
+
// lerp, NOT value-types `mixNumeric` — that wraps a NumericValue for typed style interpolation, which is
|
|
20
|
+
// overkill for a raw geometric component. The reused SPRING supplies `progress`; this only shapes it.
|
|
21
|
+
function lerp(from, to, progress) {
|
|
22
|
+
'worklet';
|
|
23
|
+
return from + (to - from) * progress;
|
|
24
|
+
}
|
|
25
|
+
function assertMeasurable(rect) {
|
|
26
|
+
'worklet';
|
|
27
|
+
// A zero/negative/non-finite dimension would divide-by-zero (or NaN) the scale — fail loud, never fabricate
|
|
28
|
+
// a garbage delta (REQ-LAYOUT-011). Position may be any finite number; only the dimensions must be > 0.
|
|
29
|
+
if (!Number.isFinite(rect.width) ||
|
|
30
|
+
!Number.isFinite(rect.height) ||
|
|
31
|
+
rect.width <= 0 ||
|
|
32
|
+
rect.height <= 0) {
|
|
33
|
+
// ui-throw-ok: unreachable from the UI path — tree.setProjection validates BOTH rects
|
|
34
|
+
// (finite fields; positive target dimensions) before calling projectAtProgress (seal r11,
|
|
35
|
+
// F2a), so this assert cannot fire from the UI-reachable set. invert's remaining callers are
|
|
36
|
+
// JS-thread (session transform, web engine, verification), where the REQ-LAYOUT-011
|
|
37
|
+
// fail-loud contract stands.
|
|
38
|
+
throw new Error(`layout: cannot project onto a rect with non-positive/non-finite dimensions (measure returned width=${rect.width}, height=${rect.height})`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The FLIP invert (REQ-LAYOUT-002): the transform that makes an element currently laid out at `after` appear
|
|
43
|
+
* at `before`. Scaling is about the top-left origin, so the top-left stays put under scale and the translate
|
|
44
|
+
* is the raw origin delta. `applyTransformToRect(invert(b, a), a)` reproduces `b` exactly.
|
|
45
|
+
*/
|
|
46
|
+
// alloc-ok: js-thread — record-building API for JS-side callers (session.transform, web engine,
|
|
47
|
+
// verification); the UI frame path inverts field-wise inside the registry's readInto.
|
|
48
|
+
export function invert(before, after) {
|
|
49
|
+
'worklet';
|
|
50
|
+
assertMeasurable(after);
|
|
51
|
+
return {
|
|
52
|
+
translateX: before.x - after.x,
|
|
53
|
+
translateY: before.y - after.y,
|
|
54
|
+
scaleX: before.width / after.width,
|
|
55
|
+
scaleY: before.height / after.height,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The projection correction at animation progress `p` (REQ-LAYOUT-002/017): lerp each component from the
|
|
60
|
+
* invert at `p=0` (element at `before`) to identity at `p=1` (element on the host layout). Recomputed from
|
|
61
|
+
* the cached before/after and the current progress — never by re-measuring.
|
|
62
|
+
*/
|
|
63
|
+
// alloc-ok: js-thread — record-building API for JS-side callers and verification; not on the UI
|
|
64
|
+
// frame path (readInto owns the per-frame projection math).
|
|
65
|
+
export function projectAtProgress(before, after, progress) {
|
|
66
|
+
'worklet';
|
|
67
|
+
const from = invert(before, after);
|
|
68
|
+
return {
|
|
69
|
+
translateX: lerp(from.translateX, IDENTITY_TRANSFORM.translateX, progress),
|
|
70
|
+
translateY: lerp(from.translateY, IDENTITY_TRANSFORM.translateY, progress),
|
|
71
|
+
scaleX: lerp(from.scaleX, IDENTITY_TRANSFORM.scaleX, progress),
|
|
72
|
+
scaleY: lerp(from.scaleY, IDENTITY_TRANSFORM.scaleY, progress),
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Apply a transform (translate + scale about the rect's top-left) to a rect, yielding the visual rect. Used
|
|
77
|
+
* for assertions and for the retarget seam's `currentVisual` (M4). Translate is in the unscaled frame; size
|
|
78
|
+
* scales in place.
|
|
79
|
+
*/
|
|
80
|
+
// alloc-ok: js-thread — record-building API for assertions and the retarget seam's JS-side
|
|
81
|
+
// currentVisual; not on the UI frame path.
|
|
82
|
+
export function applyTransformToRect(t, rect) {
|
|
83
|
+
'worklet';
|
|
84
|
+
return {
|
|
85
|
+
x: rect.x + t.translateX,
|
|
86
|
+
y: rect.y + t.translateY,
|
|
87
|
+
width: rect.width * t.scaleX,
|
|
88
|
+
height: rect.height * t.scaleY,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/** Whether a transform is within the settle epsilons of identity (translate ≤ pos eps, scale ≤ scale eps). */
|
|
92
|
+
export function isIdentity(t, epsPos = EPSILON_POS, epsScale = EPSILON_SCALE) {
|
|
93
|
+
return (Math.abs(t.translateX) < epsPos &&
|
|
94
|
+
Math.abs(t.translateY) < epsPos &&
|
|
95
|
+
Math.abs(t.scaleX - 1) < epsScale &&
|
|
96
|
+
Math.abs(t.scaleY - 1) < epsScale);
|
|
97
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// SPEC-LAYOUT REQ-LAYOUT-022 — pure scroll-offset accounting for layout measurement.
|
|
3
|
+
// Pin removeElementScroll (motion@12.42.2 create-projection-node): a viewport/window-space
|
|
4
|
+
// layout box is recovered into content space by ADDING each layoutScroll ancestor's scroll
|
|
5
|
+
// offset (HTMLProjectionNode measureScroll = instance.scrollLeft/scrollTop container scroll;
|
|
6
|
+
// DocumentProjectionNode is the always-on window root). Host-agnostic pure math: the binding
|
|
7
|
+
// supplies offsets when available; closed RN hosts that are not scroll containers contribute
|
|
8
|
+
// {0,0} this rung (stack+math only — REQ-LAYOUT-022(c)). Worklet-safe: plain number math only.
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.accountForLayoutScroll = accountForLayoutScroll;
|
|
11
|
+
/**
|
|
12
|
+
* Convert a viewport/window-space rect into content-space by adding every layoutScroll
|
|
13
|
+
* ancestor's offset (pin removeElementScroll). Zero offsets leave the rect unchanged.
|
|
14
|
+
* Offsets apply in path order (root → leaf); cumulative add is commutative for pure
|
|
15
|
+
* translation so order is documented, not load-bearing for scalar sums.
|
|
16
|
+
*/
|
|
17
|
+
function accountForLayoutScroll(rect, offsets) {
|
|
18
|
+
'worklet';
|
|
19
|
+
let x = rect.x;
|
|
20
|
+
let y = rect.y;
|
|
21
|
+
for (let i = 0; i < offsets.length; i++) {
|
|
22
|
+
const offset = offsets[i];
|
|
23
|
+
x += offset.x;
|
|
24
|
+
y += offset.y;
|
|
25
|
+
}
|
|
26
|
+
return { x, y, width: rect.width, height: rect.height };
|
|
27
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Rect } from "./types.cjs";
|
|
2
|
+
/** One layoutScroll root's scroll offset (px). Pin Point shape. */
|
|
3
|
+
export interface LayoutScrollOffset {
|
|
4
|
+
readonly x: number;
|
|
5
|
+
readonly y: number;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Convert a viewport/window-space rect into content-space by adding every layoutScroll
|
|
9
|
+
* ancestor's offset (pin removeElementScroll). Zero offsets leave the rect unchanged.
|
|
10
|
+
* Offsets apply in path order (root → leaf); cumulative add is commutative for pure
|
|
11
|
+
* translation so order is documented, not load-bearing for scalar sums.
|
|
12
|
+
*/
|
|
13
|
+
export declare function accountForLayoutScroll(rect: Rect, offsets: readonly LayoutScrollOffset[]): Rect;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Rect } from "./types.js";
|
|
2
|
+
/** One layoutScroll root's scroll offset (px). Pin Point shape. */
|
|
3
|
+
export interface LayoutScrollOffset {
|
|
4
|
+
readonly x: number;
|
|
5
|
+
readonly y: number;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Convert a viewport/window-space rect into content-space by adding every layoutScroll
|
|
9
|
+
* ancestor's offset (pin removeElementScroll). Zero offsets leave the rect unchanged.
|
|
10
|
+
* Offsets apply in path order (root → leaf); cumulative add is commutative for pure
|
|
11
|
+
* translation so order is documented, not load-bearing for scalar sums.
|
|
12
|
+
*/
|
|
13
|
+
export declare function accountForLayoutScroll(rect: Rect, offsets: readonly LayoutScrollOffset[]): Rect;
|