diff --git a/package.json b/package.json
index 1df3a47..b068fd4 100644
--- a/package.json
+++ b/package.json
@@ -36,6 +36,7 @@
"react-dom": "^18.0.0",
"react-konva": "^18.0.0-0",
"react-redux": "^7.2.6",
+ "react-resize-detector": "^7.0.0",
"react-router-dom": "^6.2.2",
"react-scripts": "5.0.0",
"react-split": "^2.0.14",
diff --git a/src/hooks/useTitle.ts b/src/hooks/useTitle.ts
new file mode 100644
index 0000000..1836ed3
--- /dev/null
+++ b/src/hooks/useTitle.ts
@@ -0,0 +1,15 @@
+import useRouteContextEffect from './useRouteContextEffect';
+import produceState from '../utils/produceState';
+
+const useTitle = (title: string) => {
+ useRouteContextEffect(
+ (setRouteContentState) => {
+ produceState(setRouteContentState, (context) => {
+ context.title = title;
+ });
+ },
+ [title]
+ );
+};
+
+export default useTitle;
diff --git a/src/pages/dataUrlViewPage/DataUrlViewPage.tsx b/src/pages/dataUrlViewPage/DataUrlViewPage.tsx
index d1b6092..f38e027 100644
--- a/src/pages/dataUrlViewPage/DataUrlViewPage.tsx
+++ b/src/pages/dataUrlViewPage/DataUrlViewPage.tsx
@@ -3,8 +3,7 @@ import useQuery from '../../hooks/useQuery';
import styles from './DataUrlViewPage.module.scss';
import { Navigate } from 'react-router-dom';
import { routes } from '../../constants/router/routes';
-import useRouteContextEffect from '../../hooks/useRouteContextEffect';
-import produceState from '../../utils/produceState';
+import useTitle from '../../hooks/useTitle';
export interface DataUrlViewPageQueryParams {
data?: string;
@@ -18,14 +17,7 @@ const DataUrlViewPage: FunctionComponent = () => {
return ;
}
- useRouteContextEffect(
- (setRouteContentState) => {
- produceState(setRouteContentState, (context) => {
- context.title = title ?? routes.dataUrlView.title;
- });
- },
- [title]
- );
+ useTitle(title ?? routes.dataUrlView.title);
return (
diff --git a/src/pages/htmlEditorPage/HtmlEditorPage.module.scss b/src/pages/htmlEditorPage/HtmlEditorPage.module.scss
index 1f60236..819b90a 100644
--- a/src/pages/htmlEditorPage/HtmlEditorPage.module.scss
+++ b/src/pages/htmlEditorPage/HtmlEditorPage.module.scss
@@ -1,5 +1,12 @@
@import '../../styles/main';
+.titleExtra {
+ flex: 1;
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+}
+
.container {
@include monacoBackground;
@@ -7,8 +14,13 @@
height: 100%;
display: flex;
flex-direction: row;
+ flex: 1;
+ overflow: hidden;
+ max-width: 100%;
.col {
+ @include monacoBackground;
+
display: flex;
flex-direction: column;
@@ -17,50 +29,23 @@
&:only-child {
flex: 1;
+
+ & > * {
+ max-width: 100%;
+ overflow: auto;
+ }
}
}
.leftCol {
- &:not(:only-child) {
- border-right: 1px solid;
- @include borderColor;
- }
-
- .editorTabs {
- flex: 1;
- display: flex;
-
- & > *:last-child {
- display: flex;
- }
-
- .editorTab {
- flex: 1;
- display: flex;
-
- .editor {
- flex: 1;
- }
- }
-
- .tabTitleWrapper {
- height: 20px !important;
- width: 50px !important;
-
- display: flex;
- flex-direction: row;
- justify-content: center;
- align-items: center;
-
- .tabTitle {
- font-size: 28px;
- }
- }
- }
}
.rightCol {
- background: white;
+ .tabTitleWrapper {
+ .tabTitle {
+ font-size: 24px;
+ }
+ }
}
.resultFrame {
@@ -68,6 +53,39 @@
border: none;
max-width: 100%;
overflow: auto;
+ background: white;
+ }
+ }
+}
+
+.editorTabs {
+ flex: 1;
+ display: flex;
+
+ & > *:last-child {
+ display: flex;
+ }
+
+ .editorTab {
+ flex: 1;
+ display: flex;
+
+ .editor {
+ flex: 1;
+ }
+ }
+
+ .tabTitleWrapper {
+ height: 20px !important;
+ width: 50px !important;
+
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ align-items: center;
+
+ .tabTitle {
+ font-size: 28px;
}
}
}
diff --git a/src/pages/htmlEditorPage/HtmlEditorPage.scss b/src/pages/htmlEditorPage/HtmlEditorPage.scss
index d07f6d3..c9b0e50 100644
--- a/src/pages/htmlEditorPage/HtmlEditorPage.scss
+++ b/src/pages/htmlEditorPage/HtmlEditorPage.scss
@@ -10,4 +10,9 @@
.gutter.gutter-horizontal {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==');
cursor: col-resize;
+ z-index: 1;
+
+ border-right: 1px solid;
+ border-left: 1px solid;
+ @include borderColor;
}
diff --git a/src/pages/htmlEditorPage/HtmlEditorPage.tsx b/src/pages/htmlEditorPage/HtmlEditorPage.tsx
index 5656531..1a7694b 100644
--- a/src/pages/htmlEditorPage/HtmlEditorPage.tsx
+++ b/src/pages/htmlEditorPage/HtmlEditorPage.tsx
@@ -1,7 +1,6 @@
import React, { CSSProperties, FunctionComponent, useCallback } from 'react';
-import PageContainer from '../../layouts/pages/pageContainer/PageContainer';
import styles from './HtmlEditorPage.module.scss';
-import { Button, Col, Row, Tabs } from 'antd';
+import { Button, Col, Row, Select, Space, Tabs, Tooltip } from 'antd';
import { useLocalstorageState } from 'rooks';
import getLocalStorageKey from '../../utils/getLocalStorageKey';
import useChangeStateHandler from '../../hooks/useChangeStateHandler';
@@ -15,10 +14,12 @@ import { OnMount } from '@monaco-editor/react';
import { emmetCSS, emmetHTML, emmetJSX } from 'emmet-monaco-es';
import { editor } from 'monaco-editor';
import ButtonGroup from 'antd/lib/button/button-group';
-import { VerticalSplit, ViewHeadline } from '@mui/icons-material';
+import { Code, VerticalSplit, ViewHeadline, Visibility } from '@mui/icons-material';
import useChangeValueStateHandler from '../../hooks/useChangeValueStateHandler';
import Split from 'react-split';
import './HtmlEditorPage.scss';
+import SingleConverterPageContainer from '../../layouts/pages/singleConverterPageContainer/SingleConverterPageContainer';
+import { EditOutlined, MinusOutlined, PlusOutlined } from '@ant-design/icons';
enum EditorTab {
HTML = 'html',
@@ -26,6 +27,11 @@ enum EditorTab {
JS = 'js'
}
+enum ViewTab {
+ PREVIEW = 'PREVIEW',
+ SOURCE = 'SOURCE'
+}
+
type EditorSources = Record;
const sourcesInitial: EditorSources = {
@@ -60,7 +66,13 @@ const tabBarStyle: CSSProperties = {
};
const editorOptions: editor.IStandaloneEditorConstructionOptions = {
- minimap: { enabled: false }
+ minimap: { enabled: false },
+ automaticLayout: false
+};
+
+const resultEditorOptions: editor.IStandaloneEditorConstructionOptions = {
+ ...editorOptions,
+ readOnly: true
};
enum ViewMode {
@@ -91,6 +103,11 @@ const HtmlEditorPage: FunctionComponent = () => {
EditorTab.HTML
);
+ const [viewTab, setViewTab] = useLocalstorageState(
+ getLocalStorageKey('html-editor', 'viewTab'),
+ ViewTab.PREVIEW
+ );
+
const [viewMode, setViewMode] = useLocalstorageState(
getLocalStorageKey('html-editor', 'viewMode'),
ViewMode.SPLIT
@@ -102,21 +119,19 @@ const HtmlEditorPage: FunctionComponent = () => {
setEditorTab(tab as EditorTab);
}, []);
+ const handleViewTabChange = useCallback((tab: string) => {
+ setViewTab(tab as ViewTab);
+ }, []);
+
const handleViewModeChange = useChangeValueStateHandler(setViewMode);
const resultSource = useDebouncedMemo(
{ sources },
({ sources }) => {
- return `
-
+ const cssPart = sources.css.trim() ? `` : '';
+ const jsPart = sources.js.trim() ? `` : '';
-${sources.html}
-
-`.trim();
+ return [cssPart, sources.html, jsPart].filter(Boolean).join('\n\n');
},
[sources],
50
@@ -126,6 +141,8 @@ ${sources.js}
emmetHTML(monaco);
emmetCSS(monaco);
emmetJSX(monaco);
+
+ editor.layout();
}, []);
// const leftColSpan = {
@@ -148,22 +165,6 @@ ${sources.js}
tabBarStyle={tabBarStyle}
className={styles.editorTabs}
tabBarGutter={10}
- tabBarExtraContent={
-
- }
- className={classNames({ 'antd-text-primary': viewMode === ViewMode.EDITOR })}
- onClick={handleViewModeChange(ViewMode.EDITOR)}
- />
- }
- className={classNames({ 'antd-text-primary': viewMode === ViewMode.SPLIT })}
- onClick={handleViewModeChange(ViewMode.SPLIT)}
- />
-
- }
>
-
+
+
+
+
+ }
+ className={styles.editorTab}
+ >
+
+
+
+
+
+ }
+ className={styles.editorTab}
+ >
+
+
+
);
+ const titleExtra = (
+
+
+
+
+
+ } />
+
+
+ } />
+
+
+ } />
+
+
+
+
+ }
+ className={classNames({ 'antd-text-primary': viewMode === ViewMode.EDITOR })}
+ onClick={handleViewModeChange(ViewMode.EDITOR)}
+ />
+ }
+ className={classNames({ 'antd-text-primary': viewMode === ViewMode.SPLIT })}
+ onClick={handleViewModeChange(ViewMode.SPLIT)}
+ />
+
+
+ );
+
return (
-
+
{viewMode === ViewMode.SPLIT ? (
{leftCol}
@@ -246,7 +314,7 @@ ${sources.js}
{viewMode === ViewMode.VIEW && rightCol}
)}
-
+
);
};
diff --git a/yarn.lock b/yarn.lock
index 22856fe..1182986 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2854,6 +2854,11 @@
dependencies:
redux "*"
+"@types/resize-observer-browser@^0.1.6":
+ version "0.1.7"
+ resolved "https://registry.yarnpkg.com/@types/resize-observer-browser/-/resize-observer-browser-0.1.7.tgz#294aaadf24ac6580b8fbd1fe3ab7b59fe85f9ef3"
+ integrity sha512-G9eN0Sn0ii9PWQ3Vl72jDPgeJwRWhv2Qk/nQkJuWmRmOB4HX3/BhD5SE1dZs/hzPZL/WKnvF0RHdTSG54QJFyg==
+
"@types/resolve@1.17.1":
version "1.17.1"
resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6"
@@ -10917,6 +10922,14 @@ react-refresh@^0.11.0:
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.11.0.tgz#77198b944733f0f1f1a90e791de4541f9f074046"
integrity sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==
+react-resize-detector@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/react-resize-detector/-/react-resize-detector-7.0.0.tgz#fbd46917ee905b7796c797aa6b301b454a6b9229"
+ integrity sha512-Xd1POfpVzH9O3F/xB/0xYy2ijtKjE/z7y4c/aJP593YSzhPy2vDhsNPjes+uQbgL1RezxJajQ679qPs8K5LAFw==
+ dependencies:
+ "@types/resize-observer-browser" "^0.1.6"
+ lodash "^4.17.21"
+
react-router-dom@^6.2.2:
version "6.2.2"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.2.2.tgz#f1a2c88365593c76b9612ae80154a13fcb72e442"