diff --git a/ivette/src/dome/renderer/data/states.ts b/ivette/src/dome/renderer/data/states.ts index fab86e0e57d922093f329dd36cbf22b244a8f072..fa2d5174b8611ff98791ca29b257894c6c1a261e 100644 --- a/ivette/src/dome/renderer/data/states.ts +++ b/ivette/src/dome/renderer/data/states.ts @@ -32,7 +32,7 @@ import Emitter from 'events'; import React from 'react'; import isEqual from 'react-fast-compare'; -import { Debug } from 'dome'; +import { Debug } from 'dome/system'; const D = new Debug('State'); diff --git a/ivette/src/dome/renderer/dialogs.tsx b/ivette/src/dome/renderer/dialogs.tsx index a1bff13059eb5f2375ff1f83eb33d25cb79a3e02..ebcebbd2edac4cacd26e97486de3ba9aa6cfd016 100644 --- a/ivette/src/dome/renderer/dialogs.tsx +++ b/ivette/src/dome/renderer/dialogs.tsx @@ -28,6 +28,7 @@ import * as filepath from 'path'; import { ipcRenderer } from 'electron'; +import { modal } from 'dome'; import * as System from 'dome/system'; // -------------------------------------------------------------------------- @@ -304,3 +305,9 @@ export async function showOpenDir( } // -------------------------------------------------------------------------- +// --- Modal +// -------------------------------------------------------------------------- +export function showModal(val: React.ReactNode): void { modal.setValue(val); } +export function closeModal(): void { showModal(undefined); } + +// -------------------------------------------------------------------------- diff --git a/ivette/src/dome/renderer/dome.tsx b/ivette/src/dome/renderer/dome.tsx index 38c44963ee933669c08a8dba1a6f14e65c9273eb..8bb7597f502619b5a27ec900d919f8b10d6ed4f2 100644 --- a/ivette/src/dome/renderer/dome.tsx +++ b/ivette/src/dome/renderer/dome.tsx @@ -45,7 +45,7 @@ import { createRoot } from 'react-dom/client'; import { ipcRenderer } from 'electron'; import SYS, * as System from 'dome/system'; -import { State } from './data/states'; +import { State, GlobalState, useGlobalState } from './data/states'; import * as Json from 'dome/data/json'; import * as Settings from 'dome/data/settings'; @@ -320,6 +320,31 @@ export function setTitle(title: string): void { ipcRenderer.send('dome.ipc.window.title', title); } +// -------------------------------------------------------------------------- +// --- Window Modal +// -------------------------------------------------------------------------- + +export const modal = new GlobalState<React.ReactNode | undefined>(undefined); + +function Modal(): JSX.Element | null { + const [ modalContent, setModalContent ] = useGlobalState(modal); + + if(modalContent === undefined) return null; + return ( + <div + className="dome-xModal-overlay" + onClick={() => setModalContent(undefined)} + > + <div + className="dome-xModal" + onClick={(event) => event.stopPropagation()} + > + {modalContent} + </div> + </div> + ); +} + // -------------------------------------------------------------------------- // --- Window Container // -------------------------------------------------------------------------- @@ -329,8 +354,9 @@ function setContainer( ): void { Settings.synchronize(); const appNode = setContextAppNode(); - if (appNode) - createRoot(appNode).render(<Component />); + if (appNode) { + createRoot(appNode).render(<><Component /><Modal /></>); + } else // eslint-disable-next-line no-console console.error('[Dome] root element #root not found.'); diff --git a/ivette/src/dome/renderer/style.css b/ivette/src/dome/renderer/style.css index ad640de4533911ff329e887669ac8c19cf4bf3e6..a0800a53d146f87763154d79d32898a59efd7cd2 100644 --- a/ivette/src/dome/renderer/style.css +++ b/ivette/src/dome/renderer/style.css @@ -211,3 +211,30 @@ input[type="checkbox"]:checked { } /* -------------------------------------------------------------------------- */ +/* --- Modal --- */ +/* -------------------------------------------------------------------------- */ +.dome-xModal { + position: absolute; + display: flex; + flex-direction: column; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + border: solid var(--border) 2px; + border-radius: 10px; + background-color: var(--background); + max-width: calc(100% - 100px); + max-height: calc(100% - 50px); + overflow: hidden; +} + +.dome-xModal-overlay { + z-index: 100; + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(50, 50, 50, .4); +} +/* -------------------------------------------------------------------------- */