134 lines
4.2 KiB
TypeScript
134 lines
4.2 KiB
TypeScript
import React from 'react';
|
|
|
|
import {
|
|
fitToViewer,
|
|
POSITION_TOP,
|
|
POSITION_BOTTOM,
|
|
POSITION_LEFT,
|
|
POSITION_RIGHT,
|
|
TOOL_NONE,
|
|
TOOL_PAN,
|
|
TOOL_ZOOM_IN,
|
|
TOOL_ZOOM_OUT,
|
|
ALIGN_LEFT,
|
|
ALIGN_TOP,
|
|
type Value,
|
|
type Tool,
|
|
type ALIGN_BOTTOM,
|
|
type ALIGN_CENTER,
|
|
type ALIGN_RIGHT,
|
|
type ToolbarPosition
|
|
} from 'react-svg-pan-zoom';
|
|
import { IconCursor } from './icon-cursor';
|
|
import { IconFit } from './icon-fit';
|
|
import { IconPan } from './icon-pan';
|
|
import { IconZoomIn } from './icon-zoom-in';
|
|
import { IconZoomOut } from './icon-zoom-out';
|
|
import { ToolbarButton } from './toolbar-button';
|
|
|
|
interface IToolbarProps {
|
|
tool: Tool
|
|
value: Value
|
|
onChangeValue: (value: Value) => void
|
|
onChangeTool: (tool: Tool) => void
|
|
activeToolColor?: string
|
|
position?: ToolbarPosition | undefined
|
|
SVGAlignX?: typeof ALIGN_CENTER | typeof ALIGN_LEFT | typeof ALIGN_RIGHT | undefined
|
|
SVGAlignY?: typeof ALIGN_CENTER | typeof ALIGN_TOP | typeof ALIGN_BOTTOM | undefined
|
|
}
|
|
|
|
export function Toolbar({
|
|
tool,
|
|
value,
|
|
onChangeValue,
|
|
onChangeTool,
|
|
activeToolColor = '#1CA6FC',
|
|
position = POSITION_RIGHT,
|
|
SVGAlignX = ALIGN_LEFT,
|
|
SVGAlignY = ALIGN_TOP
|
|
}: IToolbarProps): JSX.Element {
|
|
function handleChangeTool(event: React.MouseEvent | React.TouchEvent, tool: Tool): void {
|
|
onChangeTool(tool);
|
|
event.stopPropagation();
|
|
event.preventDefault();
|
|
};
|
|
|
|
function handleFit(event: React.MouseEvent | React.TouchEvent): void {
|
|
onChangeValue(fitToViewer(value, SVGAlignX, SVGAlignY));
|
|
event.stopPropagation();
|
|
event.preventDefault();
|
|
};
|
|
|
|
const isHorizontal = [POSITION_TOP, POSITION_BOTTOM].includes(position);
|
|
|
|
const style: React.CSSProperties = {
|
|
// position
|
|
position: 'absolute',
|
|
transform: [POSITION_TOP, POSITION_BOTTOM].includes(position) ? 'translate(-50%, 0px)' : 'none',
|
|
top: [POSITION_LEFT, POSITION_RIGHT, POSITION_TOP].includes(position) ? '5px' : 'unset',
|
|
left: [POSITION_TOP, POSITION_BOTTOM].includes(position) ? '50%' : (POSITION_LEFT === position ? '5px' : 'unset'),
|
|
right: [POSITION_RIGHT].includes(position) ? '5px' : 'unset',
|
|
bottom: [POSITION_BOTTOM].includes(position) ? '5px' : 'unset',
|
|
|
|
// inner styling
|
|
backgroundColor: 'rgba(19, 20, 22, 0.90)',
|
|
borderRadius: '2px',
|
|
display: 'flex',
|
|
flexDirection: isHorizontal ? 'row' : 'column',
|
|
padding: isHorizontal ? '1px 2px' : '2px 1px'
|
|
};
|
|
|
|
return (
|
|
<div style={style} role="toolbar">
|
|
<ToolbarButton
|
|
toolbarPosition={position}
|
|
active={tool === TOOL_NONE}
|
|
activeColor={activeToolColor}
|
|
name="unselect-tools"
|
|
title="Selection"
|
|
onClick={ (event: React.MouseEvent | React.TouchEvent) => { handleChangeTool(event, TOOL_NONE); } }>
|
|
<IconCursor/>
|
|
</ToolbarButton>
|
|
|
|
<ToolbarButton
|
|
toolbarPosition={position}
|
|
active={tool === TOOL_PAN}
|
|
activeColor={activeToolColor}
|
|
name="select-tool-pan"
|
|
title="Pan"
|
|
onClick={ (event: React.MouseEvent | React.TouchEvent) => { handleChangeTool(event, TOOL_PAN); } }>
|
|
<IconPan/>
|
|
</ToolbarButton>
|
|
|
|
<ToolbarButton
|
|
toolbarPosition={position}
|
|
active={tool === TOOL_ZOOM_IN}
|
|
activeColor={activeToolColor}
|
|
name="select-tool-zoom-in"
|
|
title="Zoom in"
|
|
onClick={ (event: React.MouseEvent | React.TouchEvent) => { handleChangeTool(event, TOOL_ZOOM_IN); } }>
|
|
<IconZoomIn/>
|
|
</ToolbarButton>
|
|
|
|
<ToolbarButton
|
|
toolbarPosition={position}
|
|
active={tool === TOOL_ZOOM_OUT}
|
|
activeColor={activeToolColor}
|
|
name="select-tool-zoom-out"
|
|
title="Zoom out"
|
|
onClick={ (event: React.MouseEvent | React.TouchEvent) => { handleChangeTool(event, TOOL_ZOOM_OUT); } }>
|
|
<IconZoomOut/>
|
|
</ToolbarButton>
|
|
|
|
<ToolbarButton
|
|
toolbarPosition={position}
|
|
active={false}
|
|
activeColor={activeToolColor}
|
|
name="fit-to-viewer"
|
|
title="Fit to viewer"
|
|
onClick={ (event: React.MouseEvent | React.TouchEvent) => { handleFit(event); } }>
|
|
<IconFit/>
|
|
</ToolbarButton>
|
|
</div>
|
|
);
|
|
}
|