Files
Dwinzo_Demo/app/src/store/visualization/useVisualizationStore.ts

86 lines
2.8 KiB
TypeScript

import { create } from "zustand";
import { immer } from "zustand/middleware/immer";
/**
* Panel position stored as percentages (0-100) of viewport dimensions
* This ensures panels stay within bounds when screen size changes
*/
interface PanelPosition {
xPercent: number; // 0-100, percentage from left edge
yPercent: number; // 0-100, percentage from top edge
}
interface VisualizationState {
editorPosition: PanelPosition | null;
setEditorPosition: (position: PanelPosition) => void;
resetEditorPosition: () => void;
}
export const useVisualizationStore = create<VisualizationState>()(
immer((set) => ({
editorPosition: null,
setEditorPosition: (position) =>
set((state) => {
state.editorPosition = position;
}),
resetEditorPosition: () =>
set((state) => {
state.editorPosition = null;
}),
}))
);
/**
* Utility functions to convert between pixels and percentages
*/
export const positionUtils = {
/**
* Convert pixel position to percentage position
*/
pixelsToPercent: (pixelX: number, pixelY: number, panelWidth: number, panelHeight: number): PanelPosition => {
const viewportWidth = window.innerWidth;
const viewportHeight = window.innerHeight;
// Calculate percentage, ensuring panel stays within bounds
const maxXPercent = ((viewportWidth - panelWidth) / viewportWidth) * 100;
const maxYPercent = ((viewportHeight - panelHeight) / viewportHeight) * 100;
const xPercent = Math.max(0, Math.min((pixelX / viewportWidth) * 100, maxXPercent));
const yPercent = Math.max(0, Math.min((pixelY / viewportHeight) * 100, maxYPercent));
return { xPercent, yPercent };
},
/**
* Convert percentage position to pixel position
*/
percentToPixels: (position: PanelPosition, panelWidth: number, panelHeight: number): { x: number; y: number } => {
const viewportWidth = window.innerWidth;
const viewportHeight = window.innerHeight;
// Calculate pixel position
let x = (position.xPercent / 100) * viewportWidth;
let y = (position.yPercent / 100) * viewportHeight;
// Ensure panel stays within bounds
const maxX = viewportWidth - panelWidth - 8;
const maxY = viewportHeight - panelHeight - 8;
x = Math.max(0, Math.min(x, maxX));
y = Math.max(0, Math.min(y, maxY));
return { x, y };
},
/**
* Get default position (top-right corner with some margin)
*/
getDefaultPosition: (panelWidth: number): PanelPosition => {
const viewportWidth = window.innerWidth;
const defaultX = Math.max(0, viewportWidth - panelWidth - 40);
const defaultY = 80;
return positionUtils.pixelsToPercent(defaultX, defaultY, panelWidth, 300);
},
};