Add editor split component (#198)

Add split and split divider component
This commit is contained in:
mrdrogdrog 2020-06-13 01:22:27 +02:00 committed by GitHub
parent c679f5524c
commit f298d1469b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 130 additions and 13 deletions

View file

@ -48,7 +48,8 @@
"react-router-dom": "5.2.0",
"react-scripts": "3.4.1",
"redux": "4.0.5",
"typescript": "3.9.5"
"typescript": "3.9.5",
"use-media": "1.4.0"
},
"scripts": {
"start": "react-scripts start",

View file

@ -0,0 +1,7 @@
.split-divider {
width: 10px;
background: white;
z-index: 1;
cursor: col-resize;
box-shadow: 3px 0 6px #e7e7e7;
}

View file

@ -0,0 +1,15 @@
import React from 'react'
import './split-divider.scss'
export interface SplitDividerProps {
onGrab: () => void
}
export const SplitDivider: React.FC<SplitDividerProps> = ({ onGrab }) => {
return (
<div
onMouseDown={() => onGrab()}
onTouchStart={() => onGrab()}
className={'split-divider'}/>
)
}

View file

@ -0,0 +1,14 @@
.splitter {
&.left {
flex: 0 1 100%;
min-width: 200px;
}
&.right {
flex: 1 0 200px;
}
&.separator {
display: flex;
}
}

View file

@ -0,0 +1,63 @@
import React, { ReactElement, useRef, useState } from 'react'
import { ShowIf } from '../show-if/show-if'
import { SplitDivider } from '../split-divider/split-divider'
import './splitter.scss'
export interface SplitterProps {
left: ReactElement
right: ReactElement
containerClassName?: string
showLeft: boolean
showRight: boolean
}
export const Splitter: React.FC<SplitterProps> = ({ containerClassName, left, right, showLeft, showRight }) => {
const [split, setSplit] = useState(50)
const realSplit = Math.max(0, Math.min(100, (showRight ? split : 100)))
const [doResizing, setDoResizing] = useState(false)
const splitContainer = useRef<HTMLDivElement>(null)
const recalculateSize = (mouseXPosition: number): void => {
if (!splitContainer.current) {
return
}
const x = mouseXPosition - splitContainer.current.offsetLeft
const newSize = x / splitContainer.current.clientWidth
setSplit(newSize * 100)
}
return (
<div ref={splitContainer} className={`flex-fill flex-row d-flex ${containerClassName || ''}`}
onMouseUp={() => setDoResizing(false)}
onTouchEnd={() => setDoResizing(false)}
onMouseMove={(mouseEvent) => {
if (doResizing) {
recalculateSize(mouseEvent.pageX)
mouseEvent.preventDefault()
}
}}
onTouchMove={(touchEvent) => {
if (doResizing) {
recalculateSize(touchEvent.touches[0].pageX)
}
}}
>
<ShowIf condition={showLeft}>
<div className={'splitter left'} style={{ flexBasis: `calc(${realSplit}% - 5px)` }}>
{left}
</div>
</ShowIf>
<ShowIf condition={showLeft && showRight}>
<div className='splitter separator'>
<SplitDivider onGrab={() => setDoResizing(true)}/>
</div>
</ShowIf>
<ShowIf condition={showRight}>
<div className='splitter right'>
{right}
</div>
</ShowIf>
</div>
)
}

View file

@ -1,7 +1,9 @@
import React from 'react'
import React, { useEffect, useState } from 'react'
import { useSelector } from 'react-redux'
import useMedia from 'use-media'
import { ApplicationState } from '../../redux'
import { ShowIf } from '../common/show-if/show-if'
import { setEditorModeConfig } from '../../redux/editor/methods'
import { Splitter } from '../common/splitter/splitter'
import { EditorWindow } from './editor-window/editor-window'
import { MarkdownPreview } from './markdown-preview/markdown-preview'
import { EditorMode } from './task-bar/editor-view-mode'
@ -13,18 +15,28 @@ interface RouteParameters {
const Editor: React.FC = () => {
const editorMode: EditorMode = useSelector((state: ApplicationState) => state.editorConfig.editorMode)
const isWide = useMedia({ minWidth: 576 })
const [firstDraw, setFirstDraw] = useState(true)
useEffect(() => {
setFirstDraw(false)
}, [])
useEffect(() => {
if (!firstDraw && !isWide && editorMode === EditorMode.BOTH) {
setEditorModeConfig(EditorMode.PREVIEW)
}
}, [editorMode, firstDraw, isWide])
return (
<div className={'d-flex flex-column vh-100'}>
<TaskBar/>
<div className={'flex-fill flex-row d-flex'}>
<ShowIf condition={editorMode === EditorMode.EDITOR || editorMode === EditorMode.BOTH}>
<EditorWindow/>
</ShowIf>
<ShowIf condition={editorMode === EditorMode.PREVIEW || editorMode === EditorMode.BOTH}>
<MarkdownPreview/>
</ShowIf>
</div>
<Splitter
showLeft={editorMode === EditorMode.EDITOR || editorMode === EditorMode.BOTH}
left={<EditorWindow/>}
showRight={editorMode === EditorMode.PREVIEW || (editorMode === EditorMode.BOTH)}
right={<MarkdownPreview/>}
containerClassName={'overflow-hidden'}/>
</div>
)
}

View file

@ -2,7 +2,7 @@ import React from 'react'
const MarkdownPreview: React.FC = () => {
return (
<div style={{ backgroundColor: 'red' }}>
<div className='h-100 px-2 py-1 bg-white'>
Hello, MarkdownPreview!
</div>
)

View file

@ -19,7 +19,7 @@ export const EditorViewMode: React.FC = () => {
<ToggleButtonGroup
type="radio"
name="options"
defaultValue={editorConfig.editorMode}
value={editorConfig.editorMode}
onChange={(value: EditorMode) => {
setEditorModeConfig(value)
}}>

View file

@ -11319,6 +11319,11 @@ url@^0.11.0:
punycode "1.3.2"
querystring "0.2.0"
use-media@1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/use-media/-/use-media-1.4.0.tgz#e777bf1f382a7aacabbd1f9ce3da2b62e58b2a98"
integrity sha512-XsgyUAf3nhzZmEfhc5MqLHwyaPjs78bgytpVJ/xDl0TF4Bptf3vEpBNBBT/EIKOmsOc8UbuECq3mrP3mt1QANA==
use@^3.1.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f"