Загрузка данных
import { Button } from 'exchange-elements/v2';
import { Observable } from 'rxjs';
import { GearIcon, TrashIcon } from '@components/Icon';
import { LegendModel, ohlcValuesToShowForMainSerie } from '@core/Legend';
import { OHLCConfig } from '@src/types';
import { formatDisplayText, useObservable } from '@src/utils';
import styles from './index.module.scss';
export interface LegendProps {
ohlcConfig?: OHLCConfig;
viewModel: Observable<LegendModel>;
}
const mainSerieKeys = new Set(ohlcValuesToShowForMainSerie);
function getEntries(values: LegendModel[number]['values']) {
return values instanceof Map ? Array.from(values.entries()) : Object.entries(values);
}
export const LegendComponent = ({ ohlcConfig, viewModel }: LegendProps) => {
const model = useObservable(viewModel);
const showMainSerieValues = Boolean(ohlcConfig?.show);
return (
<section className={styles.legend}>
{model?.map((item) => (
<div
key={`legend-${item.name}`}
className={styles.row}
>
<div className={styles.symbol}>{item.name}</div>
<div className={styles.priceWrapper}>
{getEntries(item.values).map(([key, value]) => {
if (!item.isIndicator && (!showMainSerieValues || !mainSerieKeys.has(key))) {
return null;
}
const text = formatDisplayText(value.value);
if (!text) {
return null;
}
return (
<div
key={`${item.name}-${key}`}
className={styles.item}
>
{value.name && <span>{value.name}</span>}
<span
className={styles.price}
style={{ color: value.color }}
>
{text}
</span>
</div>
);
})}
{item.settings && (
<Button
size="sm"
className={styles.button}
onClick={item.settings}
label={<GearIcon />}
/>
)}
{item.remove && (
<Button
size="sm"
className={styles.button}
onClick={item.remove}
label={<TrashIcon />}
/>
)}
</div>
</div>
))}
</section>
);
};
.legend {
position: absolute;
z-index: 10;
top: var(--space-0500);
left: var(--space-0500);
display: flex;
flex-direction: column;
gap: var(--space-0250);
pointer-events: auto;
}
.row {
width: 100%;
max-width: max-content;
display: flex;
align-items: center;
gap: var(--space-0500);
.symbol,
.item,
.price {
font-size: var(--space-0750);
font-weight: var(--font-medium);
}
.priceWrapper {
position: relative;
display: flex;
justify-content: start;
align-items: center;
gap: var(--space-0500);
}
.item {
display: flex;
align-items: center;
gap: var(--space-0250);
}
.button {
display: none;
width: var(--space-1000);
height: var(--space-1000);
border-radius: var(--space-0125);
color: var(--neutral-13);
padding: 0;
min-width: 0;
opacity: 0;
pointer-events: none;
& p {
display: flex;
justify-content: center;
align-items: start;
padding: 0;
svg {
width: var(--space-0875);
height: var(--space-0875);
}
}
}
&:hover .button {
display: block;
opacity: 1;
pointer-events: auto;
}
&:hover .item {
display: none;
opacity: 0;
pointer-events: none;
}
}