feat: expose stable journey intent signals

This commit is contained in:
2026-09-04 15:25:35 +03:00
parent c73410a956
commit 7632c8b9c0
12 changed files with 197 additions and 9 deletions

View File

@@ -5,11 +5,14 @@ declare const __PORTFOLIO_TEST_BUILD__: boolean;
const TEST_BUILD =
typeof __PORTFOLIO_TEST_BUILD__ !== "undefined" && __PORTFOLIO_TEST_BUILD__;
export type NavigationPhase = "idle" | "travelling" | "settled";
export interface NavigationState {
epoch: number;
source: JourneySource;
destinationId: SectionId | null;
signDestinationId: SectionId | null;
readonly epoch: number;
readonly source: JourneySource;
readonly phase: NavigationPhase;
readonly destinationId: SectionId | null;
readonly signDestinationId: SectionId | null;
}
export interface NavigationRuntime {
@@ -122,6 +125,7 @@ export function createNavigationController(
let currentState: NavigationState = {
epoch: 0,
source: "initial",
phase: "idle",
destinationId: null,
signDestinationId: null,
};
@@ -171,6 +175,7 @@ export function createNavigationController(
currentState = {
epoch: currentState.epoch + 1,
source,
phase: source === "passive-scroll" ? "idle" : "travelling",
destinationId,
signDestinationId,
};
@@ -211,6 +216,8 @@ export function createNavigationController(
)
return;
cancelSettle();
currentState = { ...currentState, phase: "settled" };
emit();
frameId = runtime.requestFrame(() => {
frameId = undefined;
if (
@@ -284,6 +291,14 @@ export function createNavigationController(
const epoch = beginEpoch(source, id);
if (source === "initial") {
runtime.scrollTarget(target, "instant");
if (
currentState.epoch === epoch &&
currentState.source === source &&
currentState.destinationId === id
) {
currentState = { ...currentState, phase: "settled" };
emit();
}
} else {
frameId = runtime.requestFrame(() => {
frameId = undefined;
@@ -293,6 +308,8 @@ export function createNavigationController(
currentState.destinationId === id
) {
runtime.scrollTarget(target, "instant");
currentState = { ...currentState, phase: "settled" };
emit();
}
});
}