added simple modal dialog

This commit is contained in:
Fedor Katurov 2023-04-26 15:06:26 +06:00
parent 2d11fef559
commit 3f81f6d3b3
12 changed files with 157 additions and 7 deletions

View file

@ -10,5 +10,6 @@ module.exports = {
plugins: ['react-refresh'], plugins: ['react-refresh'],
rules: { rules: {
'react-refresh/only-export-components': 'warn', 'react-refresh/only-export-components': 'warn',
'@typescript-eslint/no-empty-function': 0,
}, },
} }

View file

@ -26,6 +26,7 @@
"@remirror/react-editors": "^1.0.27", "@remirror/react-editors": "^1.0.27",
"classnames": "^2.3.2", "classnames": "^2.3.2",
"dockview": "^1.7.1", "dockview": "^1.7.1",
"formik": "^2.2.9",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-markdown": "^8.0.7", "react-markdown": "^8.0.7",

View file

@ -4,11 +4,14 @@ import { Editor } from "~/pages/editor";
import "./styles/main.scss"; import "./styles/main.scss";
import { ThemeProvider } from "./modules/theme/containers/ThemeProvider"; import { ThemeProvider } from "./modules/theme/containers/ThemeProvider";
import { SettingsProvider } from "./modules/settings/providers/SettingsProvider";
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render( ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
<React.StrictMode> <React.StrictMode>
<SettingsProvider>
<ThemeProvider> <ThemeProvider>
<Editor /> <Editor />
</ThemeProvider> </ThemeProvider>
</SettingsProvider>
</React.StrictMode> </React.StrictMode>
); );

View file

@ -6,6 +6,7 @@ import { GridLayoutItemWrapper } from "../GridLayoutItemWrapper";
import { splitLayoutVertical } from "./utils/splitLayoutVertical"; import { splitLayoutVertical } from "./utils/splitLayoutVertical";
import { splitLayoutHorizontal } from "./utils/splitLayoutHorizontal"; import { splitLayoutHorizontal } from "./utils/splitLayoutHorizontal";
import styles from "./styles.module.scss"; import styles from "./styles.module.scss";
import { useSettings } from "~/modules/settings/context/SettingsContext";
export interface GridLayoutProps { export interface GridLayoutProps {
component: FC<GridLayoutComponentProps>; component: FC<GridLayoutComponentProps>;
@ -22,6 +23,8 @@ const DefaultLayout = ({
panelProps, panelProps,
persistLayout, persistLayout,
}: DefaultLayoutProps) => { }: DefaultLayoutProps) => {
const { show: showSettings } = useSettings();
const splitVertical = useCallback(() => { const splitVertical = useCallback(() => {
splitLayoutVertical(panelProps.api.id, panelProps.containerApi); splitLayoutVertical(panelProps.api.id, panelProps.containerApi);
}, [panelProps.api.id, panelProps.containerApi]); }, [panelProps.api.id, panelProps.containerApi]);
@ -54,6 +57,7 @@ const DefaultLayout = ({
remove={remove} remove={remove}
locked={locked} locked={locked}
lock={lock} lock={lock}
showSettings={showSettings}
> >
{createElement(component, { {createElement(component, {
id: panelProps.api.id, id: panelProps.api.id,

View file

@ -14,12 +14,14 @@ type GridLayoutItemWrapperProps = PropsWithChildren & {
remove: () => void; remove: () => void;
locked: boolean; locked: boolean;
lock: () => void; lock: () => void;
showSettings: () => void;
}; };
const GridLayoutItemWrapper: FC<GridLayoutItemWrapperProps> = ({ const GridLayoutItemWrapper: FC<GridLayoutItemWrapperProps> = ({
children, children,
splitVertical, splitVertical,
splitHorizontal, splitHorizontal,
showSettings,
remove, remove,
locked, locked,
lock, lock,
@ -33,6 +35,7 @@ const GridLayoutItemWrapper: FC<GridLayoutItemWrapperProps> = ({
> >
<SplitVertical /> <SplitVertical />
</IconButton> </IconButton>
<IconButton <IconButton
onClick={splitHorizontal} onClick={splitHorizontal}
role="button" role="button"
@ -41,6 +44,14 @@ const GridLayoutItemWrapper: FC<GridLayoutItemWrapperProps> = ({
<SplitHorizontal /> <SplitHorizontal />
</IconButton> </IconButton>
<IconButton
onClick={showSettings}
role="button"
className={styles.button}
>
S
</IconButton>
{!locked && ( {!locked && (
<IconButton onClick={remove} role="button" className={styles.button}> <IconButton onClick={remove} role="button" className={styles.button}>
<DeleteIcon /> <DeleteIcon />

View file

@ -0,0 +1,16 @@
import { FC, PropsWithChildren } from "react";
import styles from "./styles.module.scss";
type ModalProps = PropsWithChildren & {
onClose: () => void;
};
const Modal: FC<ModalProps> = ({ children }) => (
<div className={styles.modal}>
<div className={styles.overlay} />
<div className={styles.content}>
<div className={styles.page}>{children}</div>
</div>
</div>
);
export { Modal };

View file

@ -0,0 +1,31 @@
.modal {
position: fixed;
inset: 0;
z-index: 100;
}
.content {
position: absolute;
inset: 0;
z-index: 2;
overflow: auto;
display: flex;
align-items: center;
justify-content: center;
padding: 16px;
box-sizing: border-box;
}
.page {
background: var(--color-background);
padding: 16px;
border-radius: 10px;
margin: auto;
}
.overlay {
position: absolute;
inset: 0;
z-index: 1;
background: rgba(0, 0, 0, 0.1);
}

View file

@ -0,0 +1,12 @@
import { FC } from "react";
const SettingsContainer: FC = () => (
<div>
<label htmlFor="color">
<input type="color" id="color" />
Sample color switch
</label>
</div>
);
export { SettingsContainer };

View file

@ -0,0 +1,12 @@
import { createContext, useContext } from "react";
export type SettingsValue = Record<string, never>;
export const defaultSettings: SettingsValue = {};
export const SettingsContext = createContext({
settings: defaultSettings,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
setSettings: (_: SettingsValue) => {},
show: () => {},
hide: () => {},
});
export const useSettings = () => useContext(SettingsContext);

View file

@ -0,0 +1,29 @@
import { FC, PropsWithChildren, useCallback, useState } from "react";
import { Modal } from "~/modules/modal/containers/Modal";
import { SettingsContainer } from "../../containers/SettingsContainer";
import {
SettingsContext,
defaultSettings,
} from "../../context/SettingsContext";
const SettingsProvider: FC<PropsWithChildren> = ({ children }) => {
const [settings, setSettings] = useState(defaultSettings);
const [settingsModalVisible, setSettingsModalVisible] = useState(false);
const show = useCallback(() => setSettingsModalVisible(true), []);
const hide = useCallback(() => setSettingsModalVisible(false), []);
return (
<SettingsContext.Provider value={{ settings, setSettings, show, hide }}>
{settingsModalVisible && (
<Modal onClose={hide}>
<SettingsContainer />
</Modal>
)}
{children}
</SettingsContext.Provider>
);
};
export { SettingsProvider };

View file

@ -18,9 +18,16 @@ body {
a { a {
color: var(--color-link); color: var(--color-link);
text-decoration: none;
&:hover {
text-decoration: underline;
}
} }
ul { ul {
padding-left: 1em;
li p { li p {
margin: 0.5em 0; margin: 0.5em 0;
} }

View file

@ -3157,6 +3157,11 @@ deepmerge@4.3.1, deepmerge@^4.2.2:
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a"
integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==
deepmerge@^2.1.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170"
integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==
defaults@^1.0.3: defaults@^1.0.3:
version "1.0.4" version "1.0.4"
resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a" resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a"
@ -3894,6 +3899,19 @@ formdata-polyfill@^4.0.10:
dependencies: dependencies:
fetch-blob "^3.1.2" fetch-blob "^3.1.2"
formik@^2.2.9:
version "2.2.9"
resolved "https://registry.yarnpkg.com/formik/-/formik-2.2.9.tgz#8594ba9c5e2e5cf1f42c5704128e119fc46232d0"
integrity sha512-LQLcISMmf1r5at4/gyJigGn0gOwFbeEAlji+N9InZF6LIMXnFNkO42sCI8Jt84YZggpD4cPWObAZaxpEFtSzNA==
dependencies:
deepmerge "^2.1.1"
hoist-non-react-statics "^3.3.0"
lodash "^4.17.21"
lodash-es "^4.17.21"
react-fast-compare "^2.0.1"
tiny-warning "^1.0.2"
tslib "^1.10.0"
fs-extra@11.1.0: fs-extra@11.1.0:
version "11.1.0" version "11.1.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.1.0.tgz#5784b102104433bb0e090f48bfc4a30742c357ed" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.1.0.tgz#5784b102104433bb0e090f48bfc4a30742c357ed"
@ -4230,7 +4248,7 @@ hastscript@^6.0.0:
property-information "^5.0.0" property-information "^5.0.0"
space-separated-tokens "^1.0.0" space-separated-tokens "^1.0.0"
hoist-non-react-statics@^3.3.1: hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1:
version "3.3.2" version "3.3.2"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
@ -4917,7 +4935,7 @@ locate-path@^6.0.0:
dependencies: dependencies:
p-locate "^5.0.0" p-locate "^5.0.0"
lodash-es@^4.17.15: lodash-es@^4.17.15, lodash-es@^4.17.21:
version "4.17.21" version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
@ -6199,6 +6217,11 @@ react-dom@^18.2.0:
loose-envify "^1.1.0" loose-envify "^1.1.0"
scheduler "^0.23.0" scheduler "^0.23.0"
react-fast-compare@^2.0.1:
version "2.0.4"
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9"
integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==
react-is@^16.13.1, react-is@^16.7.0: react-is@^16.13.1, react-is@^16.7.0:
version "16.13.1" version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
@ -7120,7 +7143,7 @@ through@2:
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==
tiny-warning@^1.0.3: tiny-warning@^1.0.2, tiny-warning@^1.0.3:
version "1.0.3" version "1.0.3"
resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
@ -7189,7 +7212,7 @@ ts-easing@^0.2.0:
resolved "https://registry.yarnpkg.com/ts-easing/-/ts-easing-0.2.0.tgz#c8a8a35025105566588d87dbda05dd7fbfa5a4ec" resolved "https://registry.yarnpkg.com/ts-easing/-/ts-easing-0.2.0.tgz#c8a8a35025105566588d87dbda05dd7fbfa5a4ec"
integrity sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ== integrity sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ==
tslib@^1.8.1: tslib@^1.10.0, tslib@^1.8.1:
version "1.14.1" version "1.14.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==