Загрузка данных


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();
}