function getCenterLabelCenterY(
entryY: number,
targetY: number,
stopY: number,
boxHeight: number,
labelOffset: number,
viewportHeight: number,
): number {
const targetSpace = Math.abs(targetY - entryY);
const stopSpace = Math.abs(stopY - entryY);
const referenceY = targetSpace < stopSpace ? stopY : targetY;
const direction = referenceY < entryY ? -1 : 1;
return clampTextBoxCenter(
entryY + direction * (labelOffset + boxHeight / 2),
boxHeight,
viewportHeight,
);
}
public setState(state: unknown): void {
if (!state || typeof state !== 'object') {
return;
}
const next = state as Partial<SliderPositionState>;
const {
hidden = this.hidden,
mode = this.mode,
startTime = this.startTime,
endTime = this.endTime,
entryPrice = this.entryPrice,
} = next;
this.hidden = hidden;
this.mode = mode;
this.startTime = startTime;
this.endTime = endTime;
this.entryPrice = entryPrice;
if (next.stopPrice !== undefined) {
const shouldNormalize = next.stopPrice !== null && this.entryPrice !== null;
this.stopPrice = shouldNormalize
? this.normalizeStop(this.entryPrice, next.stopPrice)
: next.stopPrice;
}
if (next.targetPrice !== undefined) {
const shouldNormalize = next.targetPrice !== null && this.entryPrice !== null;
this.targetPrice = shouldNormalize
? this.normalizeTarget(this.entryPrice, next.targetPrice)
: next.targetPrice;
} else if (
this.entryPrice !== null &&
this.stopPrice !== null &&
typeof next.riskRewardRatio === 'number' &&
next.riskRewardRatio >= 0
) {
const risk = Math.abs(this.entryPrice - this.stopPrice);
const direction = this.side === 'long' ? 1 : -1;
this.targetPrice = this.normalizeTarget(
this.entryPrice,
this.entryPrice + risk * next.riskRewardRatio * direction,
);
}
if (next.settings) {
this.settings = {
...createDefaultSettings(),
...next.settings,
};
}
if (typeof next.amount === 'number' && next.amount >= 0) {
this.settings.accountSize = next.amount;
}
this.render();
}
private getHandleTarget(point: Point): DragTarget {
const geometry = this.getGeometry();
if (!geometry) {
return null;
}
if (Math.abs(point.x - geometry.startX) <= HIT_TOLERANCE) {
const entryDistance = Math.abs(point.y - geometry.entryY);
if (entryDistance < 1) {
return 'entry';
}
const pointerSide = Math.sign(point.y - geometry.entryY);
const targetSide =
Math.sign(geometry.targetY - geometry.entryY) ||
-Math.sign(geometry.stopY - geometry.entryY);
if (targetSide !== 0) {
const isTargetSide = pointerSide === targetSide;
const handleY = isTargetSide ? geometry.targetY : geometry.stopY;
const handleId: SliderHandleId = isTargetSide ? 'target' : 'stop';
if (Math.abs(point.y - handleY) <= HIT_TOLERANCE) {
return handleId;
}
}
if (entryDistance <= HIT_TOLERANCE) {
return 'entry';
}
}
const handle = this.getDrawingHandleAtPoint(point);
if (handle) {
return handle.id;
}
const bounds: Bounds = {
left: geometry.leftX,
right: geometry.rightX,
top: Math.min(geometry.targetY, geometry.stopY),
bottom: Math.max(geometry.targetY, geometry.stopY),
};
return isPointInBounds(point, bounds) ? 'body' : null;
}