import React, { useEffect, useState, useRef } from 'react'; import { shallow } from 'zustand/shallow'; import { ThemeProvider } from '@mui/material/styles'; import { Box } from '@mui/material'; import { theme } from 'src/styles/theme'; import { SceneInput, IconInput, NodeInput, ConnectorInput, RectangleInput, InitialScene } from 'src/types'; import { sceneToSceneInput } from 'src/utils'; import { useSceneStore, SceneProvider } from 'src/stores/sceneStore'; import { GlobalStyles } from 'src/styles/GlobalStyles'; import { Renderer } from 'src/components/Renderer/Renderer'; import { useWindowUtils } from 'src/hooks/useWindowUtils'; import { sceneInput as sceneValidationSchema } from 'src/validation/scene'; import { UiOverlay } from 'src/components/UiOverlay/UiOverlay'; import { UiStateProvider, useUiStateStore } from 'src/stores/uiStateStore'; import { INITIAL_SCENE } from 'src/config'; import { useIconCategories } from './hooks/useIconCategories'; interface Props { initialScene?: InitialScene; disableInteractions?: boolean; onSceneUpdated?: (scene: SceneInput) => void; width?: number | string; height?: number | string; debugMode?: boolean; } const App = ({ initialScene, width, height = '100%', disableInteractions: disableInteractionsProp, onSceneUpdated, debugMode = false }: Props) => { const prevInitialScene = useRef(INITIAL_SCENE); const [isReady, setIsReady] = useState(false); useWindowUtils(); const scene = useSceneStore( ({ nodes, connectors, textBoxes, rectangles, icons }) => { return { nodes, connectors, textBoxes, rectangles, icons }; }, shallow ); const sceneActions = useSceneStore((state) => { return state.actions; }); const uiActions = useUiStateStore((state) => { return state.actions; }); const { setIconCategoriesState } = useIconCategories(); useEffect(() => { uiActions.setZoom(initialScene?.zoom ?? 1); uiActions.setDisableInteractions(Boolean(disableInteractionsProp)); }, [initialScene?.zoom, disableInteractionsProp, sceneActions, uiActions]); useEffect(() => { if (!initialScene || prevInitialScene.current === initialScene) return; const fullInitialScene = { ...INITIAL_SCENE, ...initialScene }; prevInitialScene.current = fullInitialScene; sceneActions.setScene(fullInitialScene); setIsReady(true); }, [initialScene, sceneActions, uiActions]); useEffect(() => { setIconCategoriesState(); }, [scene.icons, setIconCategoriesState]); useEffect(() => { if (!isReady || !onSceneUpdated) return; const sceneInput = sceneToSceneInput(scene); onSceneUpdated(sceneInput); }, [scene, onSceneUpdated, isReady]); useEffect(() => { uiActions.setDebugMode(debugMode); }, [debugMode, uiActions]); return ( <> ); }; export const Isoflow = (props: Props) => { return ( ); }; const useIsoflow = () => { const sceneActions = useSceneStore((state) => { return state.actions; }); const uiStateActions = useUiStateStore((state) => { return state.actions; }); return { scene: sceneActions, uiState: uiStateActions }; }; export { useIsoflow, InitialScene, SceneInput, IconInput, NodeInput, RectangleInput, ConnectorInput, sceneValidationSchema }; export const version = PACKAGE_VERSION; export const initialScene = INITIAL_SCENE; export default Isoflow;