← Files Biological Sequence & Alignment ViewerARCHIVED FILE
src/sequence/interaction-state.ts
1.78 KB · Sep 30, 2026 · 23:01 UTC
import type { SequenceFeature, SequenceSelection } from "./types";
export type SequenceInteractionState = {
activeSearchHitIndex: number;
focusCoordinate?: number;
selectedFeature?: SequenceFeature;
selectedRecordId: string;
selection?: SequenceSelection;
};
export type SequenceInteractionAction =
| { recordId: string; type: "select-record" }
| { selection: SequenceSelection; type: "select-range" }
| { coordinate: number | undefined; type: "set-focus" }
| { feature: SequenceFeature | undefined; type: "set-feature" }
| { index: number; type: "set-search-hit" }
| { type: "reset-search" }
| { type: "clear-selection" };
export function createSequenceInteractionState(
selectedRecordId: string,
): SequenceInteractionState {
return { activeSearchHitIndex: 0, selectedRecordId };
}
export function sequenceInteractionReducer(
state: SequenceInteractionState,
action: SequenceInteractionAction,
): SequenceInteractionState {
switch (action.type) {
case "select-record":
return action.recordId === state.selectedRecordId
? state
: createSequenceInteractionState(action.recordId);
case "select-range":
return {
...state,
focusCoordinate: action.selection.start,
selection: action.selection,
};
case "set-focus":
return { ...state, focusCoordinate: action.coordinate };
case "set-feature":
return { ...state, selectedFeature: action.feature };
case "set-search-hit":
return { ...state, activeSearchHitIndex: Math.max(0, action.index) };
case "reset-search":
return { ...state, activeSearchHitIndex: 0 };
case "clear-selection":
return {
...state,
focusCoordinate: undefined,
selectedFeature: undefined,
selection: undefined,
};
}
}
SHA-256: a715f5bc9314186a6843ba469aec61977165294be1f24418b469451e1f350b95