UNPKG

@kinvolk/headlamp-plugin

Version:

The needed infrastructure for building Headlamp plugins.

64 lines (63 loc) 2.93 kB
/* * Copyright 2025 The Kubernetes Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { getNodesBounds, getViewportForBounds, useReactFlow, useStore } from '@xyflow/react'; import { useCallback, useMemo } from 'react'; import { useLocalStorageState } from '../globalSearch/useLocalStorageState'; import { maxZoom, minZoom, viewportPaddingPx } from './graphConstants'; /** Helper hook to deal with viewport zooming */ export const useGraphViewport = () => { const [zoomMode, setZoomMode] = useLocalStorageState('map-zoom-mode', '100%'); const reactFlowWidth = useStore(it => it.width); const reactFlowHeight = useStore(it => it.height); const aspectRatio = useStore(it => it.width / it.height); const flow = useReactFlow(); const updateViewport = useCallback(({ nodes = flow.getNodes(), mode = zoomMode, }) => { if (mode !== zoomMode) { setZoomMode(() => mode); } const bounds = getNodesBounds(nodes); if (mode === 'fit') { const viewport = getViewportForBounds({ x: bounds.x - viewportPaddingPx, y: bounds.y - viewportPaddingPx, width: bounds.width + viewportPaddingPx * 2, height: bounds.height + viewportPaddingPx * 2, }, reactFlowWidth, reactFlowHeight, minZoom, maxZoom, 0); flow.setViewport(viewport); return; } if (mode === '100%') { const topLeftOrigin = { x: viewportPaddingPx, y: viewportPaddingPx }; const centerOrigin = { x: reactFlowWidth / 2 - bounds.width / 2, y: reactFlowHeight / 2 - bounds.height / 2, }; const xFits = bounds.width + viewportPaddingPx * 2 <= reactFlowWidth; const yFits = bounds.height + viewportPaddingPx * 2 <= reactFlowHeight; const defaultZoomViewport = { x: xFits ? centerOrigin.x : topLeftOrigin.x, y: yFits ? centerOrigin.y : topLeftOrigin.y, zoom: 1, }; flow.setViewport(defaultZoomViewport); return; } console.error('Unknown zoom mode', mode); }, // eslint-disable-next-line react-hooks/exhaustive-deps [flow, zoomMode, reactFlowWidth, reactFlowHeight]); return useMemo(() => ({ updateViewport, aspectRatio }), [updateViewport, aspectRatio]); };