Загрузка данных
import { SyntheticEvent } from 'react';
import classNames from 'classnames';
import { Button } from 'exchange-elements/v2';
import styles from './index.module.scss';
interface PriceScaleControlsProps {
isAutoScale: boolean;
isLogarithmic: boolean;
onAutoScale: () => void;
onToggleLogarithmic: () => void;
onRefresh: () => void;
}
export function PriceScaleControls({
isAutoScale,
isLogarithmic,
onAutoScale,
onToggleLogarithmic,
onRefresh,
}: PriceScaleControlsProps) {
const stopPropagation = (event: SyntheticEvent) => {
event.stopPropagation();
};
return (
<section
className={styles.root}
onMouseEnter={onRefresh}
onFocus={onRefresh}
onPointerDown={stopPropagation}
onMouseDown={stopPropagation}
onClick={stopPropagation}
>
<Button
size="sm"
className={classNames(styles.button, {
[styles.button_active]: isAutoScale,
})}
onClick={onAutoScale}
label="A"
/>
<Button
size="sm"
className={classNames(styles.button, {
[styles.button_active]: isLogarithmic,
})}
onClick={onToggleLogarithmic}
label="L"
/>
</section>
);
}
.root {
display: flex;
align-items: center;
gap: var(--space-0250);
pointer-events: auto;
}
.button {
min-width: 24px;
height: 24px;
padding: 0 var(--space-0250);
}
.button_active {
font-weight: 600;
}
static createPaneContainers() {
const legendContainer = document.createElement('div');
legendContainer.style.width = '80%';
legendContainer.style.position = 'absolute';
legendContainer.style.top = '0';
legendContainer.style.left = '0';
legendContainer.style.zIndex = ZIndex.Base;
legendContainer.style.pointerEvents = 'none';
const paneOverlayContainer = document.createElement('div');
paneOverlayContainer.className = 'moex-chart-pane-overlay-container';
paneOverlayContainer.style.position = 'absolute';
paneOverlayContainer.style.inset = '0';
paneOverlayContainer.style.zIndex = ZIndex.Base;
paneOverlayContainer.style.pointerEvents = 'none';
const leftPriceScaleControlsContainer = document.createElement('div');
leftPriceScaleControlsContainer.className = 'moex-chart-price-scale-controls-container';
leftPriceScaleControlsContainer.style.position = 'absolute';
leftPriceScaleControlsContainer.style.left = 'var(--space-0500)';
leftPriceScaleControlsContainer.style.bottom = 'var(--space-0500)';
leftPriceScaleControlsContainer.style.zIndex = ZIndex.Base;
leftPriceScaleControlsContainer.style.pointerEvents = 'none';
const rightPriceScaleControlsContainer = document.createElement('div');
rightPriceScaleControlsContainer.className = 'moex-chart-price-scale-controls-container';
rightPriceScaleControlsContainer.style.position = 'absolute';
rightPriceScaleControlsContainer.style.right = 'var(--space-0500)';
rightPriceScaleControlsContainer.style.bottom = 'var(--space-0500)';
rightPriceScaleControlsContainer.style.zIndex = ZIndex.Base;
rightPriceScaleControlsContainer.style.pointerEvents = 'none';
return {
legendContainer,
paneOverlayContainer,
leftPriceScaleControlsContainer,
rightPriceScaleControlsContainer,
};
}
.moex-chart-price-scale-controls-container {
opacity: 0;
transition: opacity 120ms ease;
}
.moex-chart-pane-price-scale-controls-host:hover .moex-chart-price-scale-controls-container,
.moex-chart-price-scale-controls-container:hover,
.moex-chart-price-scale-controls-container:focus-within {
opacity: 1;
pointer-events: auto;
}
private leftPriceScaleControlsContainer!: HTMLElement;
private rightPriceScaleControlsContainer!: HTMLElement;
private leftPriceScaleControlsRenderer!: UIRenderer;
private rightPriceScaleControlsRenderer!: UIRenderer;
private getPriceScaleMode: (target: PriceScaleTarget) => PriceScaleMode;
private togglePriceScaleMode: (target: PriceScaleTarget, mode: PriceScaleMode) => void;
public updatePriceScaleControls(): void {
this.renderPriceScaleControls(Direction.Left, this.leftPriceScaleControlsContainer, this.leftPriceScaleControlsRenderer);
this.renderPriceScaleControls(
Direction.Right,
this.rightPriceScaleControlsContainer,
this.rightPriceScaleControlsRenderer,
);
}
public setPriceScaleAutoScale(priceScaleId: Direction): void {
try {
this.getPriceScale(priceScaleId).setAutoScale(true);
} catch {
// ignore inactive price scale
}
}
public resetPriceScalesAutoScale(): void {
this.setPriceScaleAutoScale(Direction.Left);
this.setPriceScaleAutoScale(Direction.Right);
}
private renderPriceScaleControls(
priceScaleId: Direction,
container: HTMLElement,
renderer: UIRenderer,
): void {
const visible = this.isPriceScaleControlsVisible(priceScaleId);
container.style.display = visible ? '' : 'none';
if (!visible) {
return;
}
const target = this.getPriceScaleTarget(priceScaleId);
const mode = this.getPriceScaleMode(target);
renderer.renderComponent(
<PriceScaleControls
isAutoScale={this.isAutoScale(priceScaleId)}
isLogarithmic={mode === PriceScaleMode.Logarithmic}
onAutoScale={() => {
this.setPriceScaleAutoScale(priceScaleId);
this.updatePriceScaleControls();
}}
onToggleLogarithmic={() => {
this.togglePriceScaleMode(target, PriceScaleMode.Logarithmic);
this.updatePriceScaleControls();
}}
onRefresh={() => {
this.updatePriceScaleControls();
}}
/>,
);
}
private isPriceScaleControlsVisible(priceScaleId: Direction): boolean {
try {
const priceScale = this.getPriceScale(priceScaleId);
const options = priceScale.options();
if (options.visible === false) {
return false;
}
if (priceScaleId === Direction.Right) {
return true;
}
return priceScale.width() > 0;
} catch {
return false;
}
}
private isAutoScale(priceScaleId: Direction): boolean {
try {
return this.getPriceScale(priceScaleId).options().autoScale ?? true;
} catch {
return true;
}
}
public updatePriceScaleControls(): void {
this.panesMap.forEach((pane) => {
pane.updatePriceScaleControls();
});
}
public resetPriceScalesAutoScale(): void {
this.panesMap.forEach((pane) => {
pane.resetPriceScalesAutoScale();
});
this.updatePriceScaleControls();
}