mirror of
https://github.com/chartdb/chartdb.git
synced 2025-11-03 05:23:26 +00:00
* feat: add floating "Show All" button when tables are out of view * fix view of show all for mobile * fix --------- Co-authored-by: Guy Ben-Aharon <baguy3@gmail.com>
201 lines
8.0 KiB
TypeScript
201 lines
8.0 KiB
TypeScript
import React, { useCallback, useState } from 'react';
|
|
import { Card, CardContent } from '@/components/card/card';
|
|
import { ZoomIn, ZoomOut, Funnel, Redo, Undo, Scan } from 'lucide-react';
|
|
import { Separator } from '@/components/separator/separator';
|
|
import { ToolbarButton } from './toolbar-button';
|
|
import { useHistory } from '@/hooks/use-history';
|
|
import { useOnViewportChange, useReactFlow } from '@xyflow/react';
|
|
import {
|
|
Tooltip,
|
|
TooltipTrigger,
|
|
TooltipContent,
|
|
} from '@/components/tooltip/tooltip';
|
|
import { useTranslation } from 'react-i18next';
|
|
import { Button } from '@/components/button/button';
|
|
import { keyboardShortcutsForOS } from '@/context/keyboard-shortcuts-context/keyboard-shortcuts';
|
|
import { KeyboardShortcutAction } from '@/context/keyboard-shortcuts-context/keyboard-shortcuts';
|
|
import { useCanvas } from '@/hooks/use-canvas';
|
|
import { useChartDB } from '@/hooks/use-chartdb';
|
|
import { cn } from '@/lib/utils';
|
|
|
|
const convertToPercentage = (value: number) => `${Math.round(value * 100)}%`;
|
|
|
|
export interface ToolbarProps {
|
|
readonly?: boolean;
|
|
}
|
|
|
|
export const Toolbar: React.FC<ToolbarProps> = () => {
|
|
const { t } = useTranslation();
|
|
const { redo, undo, hasRedo, hasUndo } = useHistory();
|
|
const { getZoom, zoomIn, zoomOut, fitView } = useReactFlow();
|
|
const [zoom, setZoom] = useState<string>(convertToPercentage(getZoom()));
|
|
const { setShowFilter } = useCanvas();
|
|
const { hiddenTableIds } = useChartDB();
|
|
|
|
const toggleFilter = useCallback(() => {
|
|
setShowFilter((prev) => !prev);
|
|
}, [setShowFilter]);
|
|
|
|
useOnViewportChange({
|
|
onChange: ({ zoom }) => {
|
|
setZoom(convertToPercentage(zoom));
|
|
},
|
|
});
|
|
|
|
const zoomDuration = 200;
|
|
const zoomInHandler = () => {
|
|
zoomIn({ duration: zoomDuration });
|
|
};
|
|
|
|
const zoomOutHandler = () => {
|
|
zoomOut({ duration: zoomDuration });
|
|
};
|
|
|
|
const resetZoom = () => {
|
|
fitView({
|
|
minZoom: 1,
|
|
maxZoom: 1,
|
|
duration: zoomDuration,
|
|
});
|
|
};
|
|
|
|
const showAll = useCallback(() => {
|
|
fitView({
|
|
duration: 500,
|
|
padding: 0.1,
|
|
maxZoom: 0.8,
|
|
});
|
|
}, [fitView]);
|
|
|
|
return (
|
|
<div className="px-1">
|
|
<Card className="h-[44px] bg-secondary p-0 shadow-none">
|
|
<CardContent className="flex h-full flex-row items-center p-1">
|
|
<Tooltip>
|
|
<TooltipTrigger asChild>
|
|
<span>
|
|
<ToolbarButton
|
|
onClick={toggleFilter}
|
|
className={cn(
|
|
'transition-all duration-200',
|
|
{
|
|
'bg-pink-500 text-white hover:bg-pink-600 hover:text-white':
|
|
(hiddenTableIds ?? []).length >
|
|
0,
|
|
}
|
|
)}
|
|
>
|
|
<Funnel />
|
|
</ToolbarButton>
|
|
</span>
|
|
</TooltipTrigger>
|
|
<TooltipContent>
|
|
{t('toolbar.filter')}
|
|
<span className="ml-2 text-muted-foreground">
|
|
{
|
|
keyboardShortcutsForOS[
|
|
KeyboardShortcutAction.TOGGLE_FILTER
|
|
].keyCombinationLabel
|
|
}
|
|
</span>
|
|
</TooltipContent>
|
|
</Tooltip>
|
|
<Separator orientation="vertical" />
|
|
<Tooltip>
|
|
<TooltipTrigger asChild>
|
|
<span>
|
|
<ToolbarButton onClick={showAll}>
|
|
<Scan />
|
|
</ToolbarButton>
|
|
</span>
|
|
</TooltipTrigger>
|
|
<TooltipContent>
|
|
{t('toolbar.show_all')}
|
|
<span className="ml-2 text-muted-foreground">
|
|
{
|
|
keyboardShortcutsForOS[
|
|
KeyboardShortcutAction.SHOW_ALL
|
|
].keyCombinationLabel
|
|
}
|
|
</span>
|
|
</TooltipContent>
|
|
</Tooltip>
|
|
<Separator orientation="vertical" />
|
|
<Tooltip>
|
|
<TooltipTrigger asChild>
|
|
<span>
|
|
<ToolbarButton onClick={zoomOutHandler}>
|
|
<ZoomOut />
|
|
</ToolbarButton>
|
|
</span>
|
|
</TooltipTrigger>
|
|
<TooltipContent>{t('toolbar.zoom_out')}</TooltipContent>
|
|
</Tooltip>
|
|
<Button
|
|
variant="ghost"
|
|
onClick={resetZoom}
|
|
className="w-[60px] p-2 hover:bg-primary-foreground"
|
|
>
|
|
{zoom}
|
|
</Button>
|
|
<Tooltip>
|
|
<TooltipTrigger asChild>
|
|
<span>
|
|
<ToolbarButton onClick={zoomInHandler}>
|
|
<ZoomIn />
|
|
</ToolbarButton>
|
|
</span>
|
|
</TooltipTrigger>
|
|
<TooltipContent>{t('toolbar.zoom_in')}</TooltipContent>
|
|
</Tooltip>
|
|
<Separator orientation="vertical" />
|
|
<Tooltip>
|
|
<TooltipTrigger asChild>
|
|
<span>
|
|
<ToolbarButton
|
|
onClick={undo}
|
|
disabled={!hasUndo}
|
|
>
|
|
<Undo />
|
|
</ToolbarButton>
|
|
</span>
|
|
</TooltipTrigger>
|
|
<TooltipContent>
|
|
{t('toolbar.undo')}
|
|
<span className="ml-2 text-muted-foreground">
|
|
{
|
|
keyboardShortcutsForOS[
|
|
KeyboardShortcutAction.UNDO
|
|
].keyCombinationLabel
|
|
}
|
|
</span>
|
|
</TooltipContent>
|
|
</Tooltip>
|
|
<Tooltip>
|
|
<TooltipTrigger asChild>
|
|
<span>
|
|
<ToolbarButton
|
|
onClick={redo}
|
|
disabled={!hasRedo}
|
|
>
|
|
<Redo />
|
|
</ToolbarButton>
|
|
</span>
|
|
</TooltipTrigger>
|
|
<TooltipContent>
|
|
{t('toolbar.redo')}
|
|
<span className="ml-2 text-muted-foreground">
|
|
{
|
|
keyboardShortcutsForOS[
|
|
KeyboardShortcutAction.REDO
|
|
].keyCombinationLabel
|
|
}
|
|
</span>
|
|
</TooltipContent>
|
|
</Tooltip>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
);
|
|
};
|