Skip to content

Commit cd95f65

Browse files
togo01BOCOVO
authored andcommitted
Add "Fit To View" Toolbar button to quick fit all table into view.
1 parent 548bb4a commit cd95f65

File tree

3 files changed

+66
-3
lines changed

3 files changed

+66
-3
lines changed

packages/json-table-schema-visualizer/src/components/DiagramViewer/DiagramWrapper.tsx

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,40 @@ const DiagramWrapper = ({ children }: DiagramWrapperProps) => {
7373
stageStateStore.set({ scale: newScale, position: newPos });
7474
};
7575

76+
const fitToView = () => {
77+
if (stageRef.current != null) {
78+
const stage = stageRef.current;
79+
const container = stage.container();
80+
const containerWidth = container.offsetWidth;
81+
const containerHeight = container.offsetHeight;
82+
83+
const contentBounds = stage.getClientRect({ relativeTo: stage });
84+
contentBounds.x = contentBounds.x - DIAGRAM_PADDING;
85+
contentBounds.y = contentBounds.y - DIAGRAM_PADDING;
86+
contentBounds.width = contentBounds.width + 2 * DIAGRAM_PADDING;
87+
contentBounds.height = contentBounds.height + 2 * DIAGRAM_PADDING;
88+
const scaleX = containerWidth / contentBounds.width;
89+
const scaleY = containerHeight / contentBounds.height;
90+
const scale = Math.min(scaleX, scaleY);
91+
92+
stage.scale({ x: scale, y: scale });
93+
stage.position({
94+
x:
95+
(containerWidth - contentBounds.width * scale) / 2 -
96+
contentBounds.x * scale,
97+
y:
98+
(containerHeight - contentBounds.height * scale) / 2 -
99+
contentBounds.y * scale,
100+
});
101+
stage.batchDraw();
102+
stageStateStore.set({ scale, position: stage.position() });
103+
}
104+
};
105+
106+
useEffect(() => {
107+
fitToView();
108+
}, [windowWidth, windowHeight]);
109+
76110
return (
77111
<main
78112
className={`relative flex flex-col items-center ${theme === Theme.dark ? "dark" : ""}`}
@@ -94,7 +128,7 @@ const DiagramWrapper = ({ children }: DiagramWrapperProps) => {
94128
</Layer>
95129
</Stage>
96130

97-
<Toolbar />
131+
<Toolbar onFitToView={fitToView} />
98132
</main>
99133
);
100134
};
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { ExpandIcon } from "lucide-react";
2+
import PropTypes from "prop-types";
3+
4+
import ToolbarButton from "../Button";
5+
6+
interface FitToViewButtonProps {
7+
onClick: () => void;
8+
}
9+
10+
const FitToViewButton: React.FC<FitToViewButtonProps> = ({ onClick }) => {
11+
return (
12+
<ToolbarButton onClick={onClick} title="Fit-to-view">
13+
<ExpandIcon />
14+
<span className="ml-2">Fit To View</span>
15+
</ToolbarButton>
16+
);
17+
};
18+
FitToViewButton.propTypes = {
19+
onClick: PropTypes.func.isRequired,
20+
};
21+
22+
export default FitToViewButton;
Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,24 @@
1+
import PropTypes from "prop-types";
2+
13
import AutoArrangeTableButton from "./AutoArrage/AutoArrangeTables";
24
import ThemeToggler from "./ThemeToggler/ThemeToggler";
35
import DetailLevelToggle from "./DetailLevelToggle/DetailLevelToggle";
6+
import FitToViewButton from "./FitToView/FitToView";
47

5-
const Toolbar = () => {
8+
const Toolbar = ({ onFitToView }: { onFitToView: () => void }) => {
69
return (
710
<div className="flex absolute [&_svg]:w-5 [&_svg]:h-5 px-6 py-1 bottom-14 text-sm bg-gray-100 dark:bg-gray-700 shadow-lg rounded-2xl">
811
<AutoArrangeTableButton />
912
<DetailLevelToggle />
13+
<FitToViewButton onClick={onFitToView} />
1014
<hr className="w-px h-6 mx-4 my-1 bg-gray-300" />
11-
1215
<ThemeToggler />
1316
</div>
1417
);
1518
};
1619

20+
Toolbar.propTypes = {
21+
onFitToView: PropTypes.func.isRequired,
22+
};
23+
1724
export default Toolbar;

0 commit comments

Comments
 (0)