221 lines
7.1 KiB
TypeScript
221 lines
7.1 KiB
TypeScript
import { useEffect, useMemo, useState } from 'react';
|
|
import ChartToolMenu, { type ToolMenuSection } from './ChartToolMenu';
|
|
import {
|
|
IconBrush,
|
|
IconCrosshair,
|
|
IconCursor,
|
|
IconEye,
|
|
IconFib,
|
|
IconLock,
|
|
IconPlus,
|
|
IconRuler,
|
|
IconSmile,
|
|
IconText,
|
|
IconResetView,
|
|
IconTrash,
|
|
IconTrendline,
|
|
IconZoom,
|
|
IconZoomOut,
|
|
} from './ChartIcons';
|
|
|
|
type ActiveTool = 'cursor' | 'fib-retracement';
|
|
|
|
type Props = {
|
|
timeframe: string;
|
|
activeTool: ActiveTool;
|
|
hasFib: boolean;
|
|
onToolChange: (tool: ActiveTool) => void;
|
|
onZoomIn: () => void;
|
|
onZoomOut: () => void;
|
|
onResetView: () => void;
|
|
onClearFib: () => void;
|
|
};
|
|
|
|
export default function ChartSideToolbar({
|
|
timeframe,
|
|
activeTool,
|
|
hasFib,
|
|
onToolChange,
|
|
onZoomIn,
|
|
onZoomOut,
|
|
onResetView,
|
|
onClearFib,
|
|
}: Props) {
|
|
const [openMenu, setOpenMenu] = useState<'fib' | null>(null);
|
|
|
|
useEffect(() => {
|
|
if (!openMenu) return;
|
|
const onKeyDown = (e: KeyboardEvent) => {
|
|
if (e.key === 'Escape') setOpenMenu(null);
|
|
};
|
|
window.addEventListener('keydown', onKeyDown);
|
|
return () => window.removeEventListener('keydown', onKeyDown);
|
|
}, [openMenu]);
|
|
|
|
const fibMenuSections: ToolMenuSection[] = useMemo(
|
|
() => [
|
|
{
|
|
id: 'fib',
|
|
title: 'FIBONACCI',
|
|
items: [
|
|
{ id: 'fib-retracement', label: 'Fib Retracement', icon: <IconFib />, shortcut: 'Click 2 points' },
|
|
{ id: 'fib-tb-ext', label: 'Trend-Based Fib Extension', icon: <IconTrendline /> },
|
|
{ id: 'fib-channel', label: 'Fib Channel', icon: <IconFib /> },
|
|
{ id: 'fib-time-zone', label: 'Fib Time Zone', icon: <IconFib /> },
|
|
{ id: 'fib-speed-fan', label: 'Fib Speed Resistance Fan', icon: <IconFib /> },
|
|
{ id: 'fib-tb-time', label: 'Trend-Based Fib Time', icon: <IconTrendline /> },
|
|
{ id: 'fib-circles', label: 'Fib Circles', icon: <IconFib /> },
|
|
{ id: 'fib-spiral', label: 'Fib Spiral', icon: <IconFib /> },
|
|
{ id: 'fib-speed-arcs', label: 'Fib Speed Resistance Arcs', icon: <IconFib /> },
|
|
{ id: 'fib-wedge', label: 'Fib Wedge', icon: <IconFib /> },
|
|
{ id: 'pitchfan', label: 'Pitchfan', icon: <IconTrendline /> },
|
|
],
|
|
},
|
|
{
|
|
id: 'gann',
|
|
title: 'GANN',
|
|
items: [
|
|
{ id: 'gann-box', label: 'Gann Box', icon: <IconTrendline /> },
|
|
{ id: 'gann-square-fixed', label: 'Gann Square Fixed', icon: <IconTrendline /> },
|
|
{ id: 'gann-fan', label: 'Gann Fan', icon: <IconTrendline /> },
|
|
],
|
|
},
|
|
],
|
|
[]
|
|
);
|
|
|
|
return (
|
|
<div className="chartTools">
|
|
<div className="chartSideToolbar">
|
|
<button
|
|
type="button"
|
|
className={['chartToolBtn', activeTool === 'cursor' ? 'chartToolBtn--active' : ''].filter(Boolean).join(' ')}
|
|
title="Cursor"
|
|
aria-label="Cursor"
|
|
onClick={() => {
|
|
onToolChange('cursor');
|
|
setOpenMenu(null);
|
|
}}
|
|
>
|
|
<span className="chartToolBtn__icon" aria-hidden="true">
|
|
<IconCursor />
|
|
</span>
|
|
</button>
|
|
|
|
<button type="button" className="chartToolBtn" title="Crosshair" aria-label="Crosshair" disabled>
|
|
<span className="chartToolBtn__icon" aria-hidden="true">
|
|
<IconCrosshair />
|
|
</span>
|
|
</button>
|
|
|
|
<button type="button" className="chartToolBtn" title="Add" aria-label="Add" disabled>
|
|
<span className="chartToolBtn__icon" aria-hidden="true">
|
|
<IconPlus />
|
|
</span>
|
|
</button>
|
|
|
|
<button type="button" className="chartToolBtn" title="Trendline" aria-label="Trendline" disabled>
|
|
<span className="chartToolBtn__icon" aria-hidden="true">
|
|
<IconTrendline />
|
|
</span>
|
|
</button>
|
|
|
|
<button
|
|
type="button"
|
|
className={['chartToolBtn', activeTool === 'fib-retracement' ? 'chartToolBtn--active' : ''].filter(Boolean).join(' ')}
|
|
title="Fibonacci"
|
|
aria-label="Fibonacci"
|
|
onClick={() => setOpenMenu((m) => (m === 'fib' ? null : 'fib'))}
|
|
>
|
|
<span className="chartToolBtn__icon" aria-hidden="true">
|
|
<IconFib />
|
|
</span>
|
|
</button>
|
|
|
|
<button type="button" className="chartToolBtn" title="Brush" aria-label="Brush" disabled>
|
|
<span className="chartToolBtn__icon" aria-hidden="true">
|
|
<IconBrush />
|
|
</span>
|
|
</button>
|
|
|
|
<button type="button" className="chartToolBtn" title="Text" aria-label="Text" disabled>
|
|
<span className="chartToolBtn__icon" aria-hidden="true">
|
|
<IconText />
|
|
</span>
|
|
</button>
|
|
|
|
<button type="button" className="chartToolBtn" title="Emoji" aria-label="Emoji" disabled>
|
|
<span className="chartToolBtn__icon" aria-hidden="true">
|
|
<IconSmile />
|
|
</span>
|
|
</button>
|
|
|
|
<button type="button" className="chartToolBtn" title="Ruler" aria-label="Ruler" disabled>
|
|
<span className="chartToolBtn__icon" aria-hidden="true">
|
|
<IconRuler />
|
|
</span>
|
|
</button>
|
|
|
|
<div className="chartToolBtn__spacer" />
|
|
|
|
<button type="button" className="chartToolBtn" title="Zoom In" aria-label="Zoom In" onClick={onZoomIn}>
|
|
<span className="chartToolBtn__icon" aria-hidden="true">
|
|
<IconZoom />
|
|
</span>
|
|
</button>
|
|
|
|
<button type="button" className="chartToolBtn" title="Zoom Out" aria-label="Zoom Out" onClick={onZoomOut}>
|
|
<span className="chartToolBtn__icon" aria-hidden="true">
|
|
<IconZoomOut />
|
|
</span>
|
|
</button>
|
|
|
|
<button type="button" className="chartToolBtn" title="Reset View" aria-label="Reset View" onClick={onResetView}>
|
|
<span className="chartToolBtn__icon" aria-hidden="true">
|
|
<IconResetView />
|
|
</span>
|
|
</button>
|
|
|
|
<button type="button" className="chartToolBtn" title="Lock" aria-label="Lock" disabled>
|
|
<span className="chartToolBtn__icon" aria-hidden="true">
|
|
<IconLock />
|
|
</span>
|
|
</button>
|
|
|
|
<button
|
|
type="button"
|
|
className="chartToolBtn"
|
|
title="Clear Fib"
|
|
aria-label="Clear Fib"
|
|
onClick={onClearFib}
|
|
disabled={!hasFib}
|
|
>
|
|
<span className="chartToolBtn__icon" aria-hidden="true">
|
|
<IconTrash />
|
|
</span>
|
|
</button>
|
|
|
|
<button type="button" className="chartToolBtn" title="Visibility" aria-label="Visibility" disabled>
|
|
<span className="chartToolBtn__icon" aria-hidden="true">
|
|
<IconEye />
|
|
</span>
|
|
</button>
|
|
</div>
|
|
|
|
{openMenu === 'fib' ? (
|
|
<>
|
|
<div className="chartToolMenuBackdrop" onClick={() => setOpenMenu(null)} />
|
|
<ChartToolMenu
|
|
timeframeLabel={timeframe}
|
|
sections={fibMenuSections}
|
|
onSelectItem={(id) => {
|
|
if (id === 'fib-retracement') onToolChange('fib-retracement');
|
|
setOpenMenu(null);
|
|
}}
|
|
/>
|
|
</>
|
|
) : null}
|
|
</div>
|
|
);
|
|
}
|