mirror of
https://github.com/hanzoai/sentinel.git
synced 2026-09-29 22:34:33 +00:00
121 lines
3.3 KiB
TypeScript
121 lines
3.3 KiB
TypeScript
import {Component, createContext} from 'react';
|
|
|
|
import {rectOfContent} from 'sentry/components/performance/waterfall/utils';
|
|
import clamp from 'sentry/utils/number/clamp';
|
|
|
|
import type {DragManagerChildrenProps} from './dragManager';
|
|
import type {ParsedTraceType} from './types';
|
|
|
|
export type CursorGuideManagerChildrenProps = {
|
|
displayCursorGuide: (mousePageX: number) => void;
|
|
hideCursorGuide: () => void;
|
|
mouseLeft: number | undefined;
|
|
|
|
showCursorGuide: boolean;
|
|
traceViewMouseLeft: number | undefined;
|
|
};
|
|
|
|
const CursorGuideManagerContext = createContext<CursorGuideManagerChildrenProps>({
|
|
showCursorGuide: false,
|
|
mouseLeft: void 0,
|
|
traceViewMouseLeft: void 0,
|
|
|
|
displayCursorGuide: () => {},
|
|
hideCursorGuide: () => {},
|
|
});
|
|
|
|
type PropType = {
|
|
children: React.ReactNode;
|
|
dragProps: DragManagerChildrenProps;
|
|
// this is the DOM element where the drag events occur. it's also the reference point
|
|
// for calculating the relative mouse x coordinate.
|
|
interactiveLayerRef: React.RefObject<HTMLDivElement>;
|
|
|
|
trace: ParsedTraceType;
|
|
};
|
|
|
|
type StateType = {
|
|
mouseLeft: number | undefined;
|
|
showCursorGuide: boolean;
|
|
traceViewMouseLeft: number | undefined;
|
|
};
|
|
|
|
export class Provider extends Component<PropType, StateType> {
|
|
state: StateType = {
|
|
showCursorGuide: false,
|
|
mouseLeft: void 0,
|
|
traceViewMouseLeft: void 0,
|
|
};
|
|
|
|
hasInteractiveLayer = (): boolean => !!this.props.interactiveLayerRef.current;
|
|
|
|
displayCursorGuide = (mousePageX: number) => {
|
|
if (!this.hasInteractiveLayer()) {
|
|
return;
|
|
}
|
|
|
|
const {trace, dragProps} = this.props;
|
|
|
|
const interactiveLayer = this.props.interactiveLayerRef.current!;
|
|
|
|
const rect = rectOfContent(interactiveLayer);
|
|
|
|
// duration of the entire trace in seconds
|
|
const traceDuration = trace.traceEndTimestamp - trace.traceStartTimestamp;
|
|
|
|
const viewStart = dragProps.viewWindowStart;
|
|
const viewEnd = dragProps.viewWindowEnd;
|
|
|
|
const viewStartTimestamp = trace.traceStartTimestamp + viewStart * traceDuration;
|
|
const viewEndTimestamp = trace.traceEndTimestamp - (1 - viewEnd) * traceDuration;
|
|
const viewDuration = viewEndTimestamp - viewStartTimestamp;
|
|
|
|
// clamp mouseLeft to be within [0, 1]
|
|
const mouseLeft = clamp((mousePageX - rect.x) / rect.width, 0, 1);
|
|
|
|
const duration =
|
|
mouseLeft * Math.abs(trace.traceEndTimestamp - trace.traceStartTimestamp);
|
|
|
|
const startTimestamp = trace.traceStartTimestamp + duration;
|
|
|
|
const start = (startTimestamp - viewStartTimestamp) / viewDuration;
|
|
|
|
this.setState({
|
|
showCursorGuide: true,
|
|
mouseLeft,
|
|
traceViewMouseLeft: start,
|
|
});
|
|
};
|
|
|
|
hideCursorGuide = () => {
|
|
if (!this.hasInteractiveLayer()) {
|
|
return;
|
|
}
|
|
|
|
this.setState({
|
|
showCursorGuide: false,
|
|
mouseLeft: void 0,
|
|
traceViewMouseLeft: void 0,
|
|
});
|
|
};
|
|
|
|
render() {
|
|
const childrenProps = {
|
|
showCursorGuide: this.state.showCursorGuide,
|
|
mouseLeft: this.state.mouseLeft,
|
|
traceViewMouseLeft: this.state.traceViewMouseLeft,
|
|
|
|
displayCursorGuide: this.displayCursorGuide,
|
|
hideCursorGuide: this.hideCursorGuide,
|
|
};
|
|
|
|
return (
|
|
<CursorGuideManagerContext.Provider value={childrenProps}>
|
|
{this.props.children}
|
|
</CursorGuideManagerContext.Provider>
|
|
);
|
|
}
|
|
}
|
|
|
|
export const Consumer = CursorGuideManagerContext.Consumer;
|