diff --git a/docs/pages/docs/api/index.mdx b/docs/pages/docs/api/index.mdx
index 53ba14f..d96371d 100644
--- a/docs/pages/docs/api/index.mdx
+++ b/docs/pages/docs/api/index.mdx
@@ -7,4 +7,5 @@
| `height` | `number` \| `string` | Height of the Isoflow renderer as a CSS value. | `100%` |
| `onSceneUpdate` | `function` | A callback that is triggered whenever an item is added, updated or removed from the scene. The callback is called with the updated scene as the first argument. | `undefined` |
| `enableDebugTools` | `boolean` | Enables extra tools for debugging purposes. | `false` |
-| `editorMode` | `EXPLORABLE_READONLY` \| `NON_INTERACTIVE` \| `EDITABLE` | Enables / disables editor features. | `EDITABLE` |
\ No newline at end of file
+| `editorMode` | `EXPLORABLE_READONLY` \| `NON_INTERACTIVE` \| `EDITABLE` | Enables / disables editor features. | `EDITABLE` |
+| `mainMenuOptions` | `(OPEN \| SAVE_JSON \| CLEAR \| GITHUB \| DISCORD \| VERSION)[]` | Shows / hides options in the main menu. If `[]` is passed, the menu is hidden. | `['OPEN', 'SAVE_JSON', 'CLEAR', 'GITHUB', 'DISCORD', 'VERSION']` |
\ No newline at end of file
diff --git a/src/Isoflow.tsx b/src/Isoflow.tsx
index 0518f08..1586afc 100644
--- a/src/Isoflow.tsx
+++ b/src/Isoflow.tsx
@@ -20,11 +20,12 @@ 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 { INITIAL_SCENE, MAIN_MENU_OPTIONS } from 'src/config';
import { useIconCategories } from './hooks/useIconCategories';
const App = ({
initialScene,
+ mainMenuOptions = MAIN_MENU_OPTIONS,
width = '100%',
height = '100%',
onSceneUpdated,
@@ -51,7 +52,14 @@ const App = ({
useEffect(() => {
uiActions.setZoom(initialScene?.zoom ?? 1);
uiActions.setEditorMode(editorMode);
- }, [initialScene?.zoom, editorMode, sceneActions, uiActions]);
+ uiActions.setMainMenuOptions(mainMenuOptions);
+ }, [
+ initialScene?.zoom,
+ editorMode,
+ sceneActions,
+ uiActions,
+ mainMenuOptions
+ ]);
useEffect(() => {
return () => {
diff --git a/src/components/MainMenu/MainMenu.tsx b/src/components/MainMenu/MainMenu.tsx
index 02221cb..f25db6e 100644
--- a/src/components/MainMenu/MainMenu.tsx
+++ b/src/components/MainMenu/MainMenu.tsx
@@ -1,4 +1,4 @@
-import React, { useState, useCallback } from 'react';
+import React, { useState, useCallback, useMemo } from 'react';
import { Menu, Typography, Divider, Card } from '@mui/material';
import {
Menu as MenuIcon,
@@ -22,6 +22,9 @@ export const MainMenu = () => {
const isMainMenuOpen = useUiStateStore((state) => {
return state.isMainMenuOpen;
});
+ const mainMenuOptions = useUiStateStore((state) => {
+ return state.mainMenuOptions;
+ });
const scene = useSceneStore((state) => {
return {
title: state.title,
@@ -95,6 +98,25 @@ export const MainMenu = () => {
uiStateActions.setIsMainMenuOpen(false);
}, [uiStateActions, setScene]);
+ const sectionVisibility = useMemo(() => {
+ return {
+ actions: Boolean(
+ mainMenuOptions.includes('OPEN') ||
+ mainMenuOptions.includes('SAVE_JSON') ||
+ mainMenuOptions.includes('CLEAR')
+ ),
+ links: Boolean(
+ mainMenuOptions.includes('GITHUB') ||
+ mainMenuOptions.includes('DISCORD')
+ ),
+ version: Boolean(mainMenuOptions.includes('VERSION'))
+ };
+ }, [mainMenuOptions]);
+
+ if (mainMenuOptions.length === 0) {
+ return null;
+ }
+
return (
} name="Main menu" onClick={onToggleMenu} />
@@ -117,38 +139,65 @@ export const MainMenu = () => {
}}
>
- }>
- Open
-
- }>
- Download diagram
-
- }>
- Clear the canvas
-
-
-
-
-
-
+ {mainMenuOptions.includes('OPEN') && (
+ }>
+ Open
+
+ )}
+
+ {mainMenuOptions.includes('SAVE_JSON') && (
+ }>
+ Download diagram
+
+ )}
+
+ {mainMenuOptions.includes('CLEAR') && (
+ }>
+ Clear the canvas
+
+ )}
+
+ {sectionVisibility.links && (
+ <>
+
+
+ {mainMenuOptions.includes('GITHUB') && (
+
+ )}
+
+ {mainMenuOptions.includes('DISCORD') && (
+
+ )}
+ >
+ )}
+
+ {sectionVisibility.version && (
+ <>
+
+
+ {mainMenuOptions.includes('VERSION') && (
+
+ )}
+ >
+ )}
diff --git a/src/config.ts b/src/config.ts
index 2d02d46..a098df2 100644
--- a/src/config.ts
+++ b/src/config.ts
@@ -1,4 +1,10 @@
-import { Size, Coords, SceneInput, Connector } from 'src/types';
+import {
+ Size,
+ Coords,
+ SceneInput,
+ Connector,
+ MainMenuOptions
+} from 'src/types';
import { customVars } from './styles/theme';
// TODO: This file could do with better organisation and convention for easier reading.
@@ -53,3 +59,12 @@ export const INITIAL_SCENE: SceneInput = {
textBoxes: [],
rectangles: []
};
+export const MAIN_MENU_OPTIONS: MainMenuOptions = [
+ 'CLEAR',
+ 'OPEN',
+ 'SAVE_JSON',
+ 'CLEAR',
+ 'DISCORD',
+ 'GITHUB',
+ 'VERSION'
+];
diff --git a/src/stores/uiStateStore.tsx b/src/stores/uiStateStore.tsx
index 2088ec4..267e9b4 100644
--- a/src/stores/uiStateStore.tsx
+++ b/src/stores/uiStateStore.tsx
@@ -11,6 +11,7 @@ import { UiStateStore } from 'src/types';
const initialState = () => {
return createStore((set, get) => {
return {
+ mainMenuOptions: [],
editorMode: 'EXPLORABLE_READONLY',
mode: getStartingMode('EXPLORABLE_READONLY'),
iconCategoriesState: [],
@@ -31,6 +32,9 @@ const initialState = () => {
zoom: 1,
rendererSize: { width: 0, height: 0 },
actions: {
+ setMainMenuOptions: (mainMenuOptions) => {
+ set({ mainMenuOptions });
+ },
setEditorMode: (mode) => {
set({ editorMode: mode, mode: getStartingMode(mode) });
},
diff --git a/src/types/common.ts b/src/types/common.ts
index 8cda0ad..17049de 100644
--- a/src/types/common.ts
+++ b/src/types/common.ts
@@ -30,3 +30,14 @@ export const EditorModeEnum = {
EXPLORABLE_READONLY: 'EXPLORABLE_READONLY',
EDITABLE: 'EDITABLE'
} as const;
+
+export const MainMenuOptionsEnum = {
+ OPEN: 'OPEN',
+ SAVE_JSON: 'SAVE_JSON',
+ CLEAR: 'CLEAR',
+ GITHUB: 'GITHUB',
+ DISCORD: 'DISCORD',
+ VERSION: 'VERSION'
+} as const;
+
+export type MainMenuOptions = (keyof typeof MainMenuOptionsEnum)[];
diff --git a/src/types/inputs.ts b/src/types/inputs.ts
index a1fa1ec..e4d8beb 100644
--- a/src/types/inputs.ts
+++ b/src/types/inputs.ts
@@ -9,7 +9,7 @@ import {
connectorStyleEnum
} from 'src/validation/sceneItems';
import { sceneInput } from 'src/validation/scene';
-import type { EditorModeEnum } from './common';
+import type { EditorModeEnum, MainMenuOptions } from './common';
export type ConnectorStyleEnum = z.infer;
export type IconInput = z.infer;
@@ -26,6 +26,7 @@ export type InitialScene = Partial & {
export interface IsoflowProps {
initialScene?: InitialScene;
+ mainMenuOptions?: MainMenuOptions;
onSceneUpdated?: (scene: SceneInput) => void;
width?: number | string;
height?: number | string;
diff --git a/src/types/ui.ts b/src/types/ui.ts
index 7cd6b8b..7467256 100644
--- a/src/types/ui.ts
+++ b/src/types/ui.ts
@@ -1,4 +1,4 @@
-import { Coords, Size, EditorModeEnum } from './common';
+import { Coords, Size, EditorModeEnum, MainMenuOptions } from './common';
import { SceneItem, Connector, SceneItemReference } from './scene';
import { IconInput } from './inputs';
@@ -154,6 +154,7 @@ export type IconCollectionStateWithIcons = IconCollectionState & {
};
export interface UiState {
+ mainMenuOptions: MainMenuOptions;
editorMode: keyof typeof EditorModeEnum;
iconCategoriesState: IconCollectionState[];
mode: Mode;
@@ -168,6 +169,7 @@ export interface UiState {
}
export interface UiStateActions {
+ setMainMenuOptions: (options: MainMenuOptions) => void;
setEditorMode: (mode: keyof typeof EditorModeEnum) => void;
setIconCategoriesState: (iconCategoriesState: IconCollectionState[]) => void;
resetUiState: () => void;