Resizable split pane (#190)
* Integrating with react-split-pane * block event while resizing panels * bring scrollsync back * fixed footer position
This commit is contained in:
parent
d6292bf4ff
commit
635049b8db
@ -135,6 +135,7 @@
|
|||||||
"react-sidebar": "^2.2.1",
|
"react-sidebar": "^2.2.1",
|
||||||
"react-simple-dnd": "^0.1.2",
|
"react-simple-dnd": "^0.1.2",
|
||||||
"react-sortable": "^1.2.0",
|
"react-sortable": "^1.2.0",
|
||||||
|
"react-split-pane": "^0.1.57",
|
||||||
"react-toolbox": "^1.2.1",
|
"react-toolbox": "^1.2.1",
|
||||||
"react-topbar-progress-indicator": "^1.0.0",
|
"react-topbar-progress-indicator": "^1.0.0",
|
||||||
"react-waypoint": "^3.1.3",
|
"react-waypoint": "^3.1.3",
|
||||||
|
@ -4,34 +4,37 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.root {
|
.root {
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container {
|
|
||||||
display: flex;
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer {
|
|
||||||
flex: 0;
|
|
||||||
padding: 10px 20px;
|
|
||||||
border-top: 1px solid var(--defaultColorLight);
|
|
||||||
background: var(--backgroundColor);
|
|
||||||
text-align: right;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.controlPane {
|
.controlPane {
|
||||||
flex: 1;
|
height: calc(100% - 55px);
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
padding: 0 20px;
|
padding: 0 20px;
|
||||||
border-right: 1px solid var(--defaultColorLight);
|
border-right: 1px solid var(--defaultColorLight);
|
||||||
}
|
}
|
||||||
|
|
||||||
.previewPane {
|
.previewPane {
|
||||||
flex: 1;
|
height: calc(100% - 55px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.blocker {
|
||||||
|
}
|
||||||
|
|
||||||
|
.blocker > * {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
height: 55px;
|
||||||
|
padding: 10px 20px;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 9999;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
border-top: 1px solid var(--defaultColorLight);
|
||||||
|
background: var(--backgroundColor);
|
||||||
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,27 @@
|
|||||||
import React, { PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
|
import SplitPane from 'react-split-pane';
|
||||||
import { ScrollSync, ScrollSyncPane } from '../ScrollSync';
|
import { ScrollSync, ScrollSyncPane } from '../ScrollSync';
|
||||||
import ControlPane from '../ControlPanel/ControlPane';
|
import ControlPane from '../ControlPanel/ControlPane';
|
||||||
import PreviewPane from '../PreviewPane/PreviewPane';
|
import PreviewPane from '../PreviewPane/PreviewPane';
|
||||||
import Toolbar from './EntryEditorToolbar';
|
import Toolbar from './EntryEditorToolbar';
|
||||||
import styles from './EntryEditor.css';
|
import styles from './EntryEditor.css';
|
||||||
|
|
||||||
export default function EntryEditor(
|
class EntryEditor extends Component {
|
||||||
{
|
state = {
|
||||||
|
showEventBlocker: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
handleSplitPaneDragStart = () => {
|
||||||
|
this.setState({ showEventBlocker: true });
|
||||||
|
};
|
||||||
|
|
||||||
|
handleSplitPaneDragFinished = () => {
|
||||||
|
this.setState({ showEventBlocker: false });
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
collection,
|
collection,
|
||||||
entry,
|
entry,
|
||||||
fields,
|
fields,
|
||||||
@ -17,13 +31,22 @@ export default function EntryEditor(
|
|||||||
onRemoveMedia,
|
onRemoveMedia,
|
||||||
onPersist,
|
onPersist,
|
||||||
onCancelEdit,
|
onCancelEdit,
|
||||||
}) {
|
} = this.props;
|
||||||
|
|
||||||
|
const controlClassName = `${ styles.controlPane } ${ this.state.showEventBlocker && styles.blocker }`;
|
||||||
|
const previewClassName = `${ styles.previewPane } ${ this.state.showEventBlocker && styles.blocker }`;
|
||||||
return (
|
return (
|
||||||
<div className={styles.root}>
|
<div className={styles.root}>
|
||||||
<ScrollSync>
|
<ScrollSync>
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
|
<SplitPane
|
||||||
|
defaultSize="50%"
|
||||||
|
onDragStarted={this.handleSplitPaneDragStart}
|
||||||
|
onDragFinished={this.handleSplitPaneDragFinished}
|
||||||
|
>
|
||||||
<ScrollSyncPane>
|
<ScrollSyncPane>
|
||||||
<div className={styles.controlPane}>
|
<div className={controlClassName}>
|
||||||
|
|
||||||
<ControlPane
|
<ControlPane
|
||||||
collection={collection}
|
collection={collection}
|
||||||
entry={entry}
|
entry={entry}
|
||||||
@ -33,9 +56,10 @@ export default function EntryEditor(
|
|||||||
onAddMedia={onAddMedia}
|
onAddMedia={onAddMedia}
|
||||||
onRemoveMedia={onRemoveMedia}
|
onRemoveMedia={onRemoveMedia}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</ScrollSyncPane>
|
</ScrollSyncPane>
|
||||||
<div className={styles.previewPane}>
|
<div className={previewClassName}>
|
||||||
<PreviewPane
|
<PreviewPane
|
||||||
collection={collection}
|
collection={collection}
|
||||||
entry={entry}
|
entry={entry}
|
||||||
@ -43,6 +67,7 @@ export default function EntryEditor(
|
|||||||
getMedia={getMedia}
|
getMedia={getMedia}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</SplitPane>
|
||||||
</div>
|
</div>
|
||||||
</ ScrollSync>
|
</ ScrollSync>
|
||||||
<div className={styles.footer}>
|
<div className={styles.footer}>
|
||||||
@ -52,9 +77,11 @@ export default function EntryEditor(
|
|||||||
onCancelEdit={onCancelEdit}
|
onCancelEdit={onCancelEdit}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
EntryEditor.propTypes = {
|
EntryEditor.propTypes = {
|
||||||
collection: ImmutablePropTypes.map.isRequired,
|
collection: ImmutablePropTypes.map.isRequired,
|
||||||
@ -67,3 +94,6 @@ EntryEditor.propTypes = {
|
|||||||
onRemoveMedia: PropTypes.func.isRequired,
|
onRemoveMedia: PropTypes.func.isRequired,
|
||||||
onCancelEdit: PropTypes.func.isRequired,
|
onCancelEdit: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export default EntryEditor;
|
||||||
|
@ -92,6 +92,38 @@ h1 {
|
|||||||
background-color: #ddd;
|
background-color: #ddd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
& .Resizer {
|
||||||
|
background: #000;
|
||||||
|
opacity: .2;
|
||||||
|
z-index: 1;
|
||||||
|
box-sizing: border-box;
|
||||||
|
background-clip: padding-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
& .Resizer:hover {
|
||||||
|
-webkit-transition: all 2s ease;
|
||||||
|
transition: all 2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
& .Resizer.vertical {
|
||||||
|
width: 11px;
|
||||||
|
margin: 0 -5px;
|
||||||
|
border-left: 5px solid rgba(255, 255, 255, 0);
|
||||||
|
border-right: 5px solid rgba(255, 255, 255, 0);
|
||||||
|
cursor: col-resize;
|
||||||
|
}
|
||||||
|
|
||||||
|
& .Resizer.vertical:hover {
|
||||||
|
border-left: 5px solid rgba(0, 0, 0, 0.5);
|
||||||
|
border-right: 5px solid rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
& .Resizer.disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
& .Resizer.disabled:hover {
|
||||||
|
border-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
& .rdt {
|
& .rdt {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
26
yarn.lock
26
yarn.lock
@ -1175,6 +1175,10 @@ boom@2.x.x:
|
|||||||
dependencies:
|
dependencies:
|
||||||
hoek "2.x.x"
|
hoek "2.x.x"
|
||||||
|
|
||||||
|
bowser@^1.0.0:
|
||||||
|
version "1.6.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/bowser/-/bowser-1.6.0.tgz#37fc387b616cb6aef370dab4d6bd402b74c5c54d"
|
||||||
|
|
||||||
boxen@^0.3.1:
|
boxen@^0.3.1:
|
||||||
version "0.3.1"
|
version "0.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/boxen/-/boxen-0.3.1.tgz#a7d898243ae622f7abb6bb604d740a76c6a5461b"
|
resolved "https://registry.yarnpkg.com/boxen/-/boxen-0.3.1.tgz#a7d898243ae622f7abb6bb604d740a76c6a5461b"
|
||||||
@ -3538,6 +3542,10 @@ https-browserify@0.0.1:
|
|||||||
version "0.0.1"
|
version "0.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-0.0.1.tgz#3f91365cabe60b77ed0ebba24b454e3e09d95a82"
|
resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-0.0.1.tgz#3f91365cabe60b77ed0ebba24b454e3e09d95a82"
|
||||||
|
|
||||||
|
hyphenate-style-name@^1.0.1:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.2.tgz#31160a36930adaf1fc04c6074f7eb41465d4ec4b"
|
||||||
|
|
||||||
iconv-lite@^0.4.13, iconv-lite@~0.4.13, iconv-lite@0.4.13:
|
iconv-lite@^0.4.13, iconv-lite@~0.4.13, iconv-lite@0.4.13:
|
||||||
version "0.4.13"
|
version "0.4.13"
|
||||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.13.tgz#1f88aba4ab0b1508e8312acc39345f36e992e2f2"
|
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.13.tgz#1f88aba4ab0b1508e8312acc39345f36e992e2f2"
|
||||||
@ -3643,6 +3651,13 @@ inline-process-browser@^1.0.0:
|
|||||||
falafel "^1.0.1"
|
falafel "^1.0.1"
|
||||||
through2 "^0.6.5"
|
through2 "^0.6.5"
|
||||||
|
|
||||||
|
inline-style-prefixer@^2.0.4:
|
||||||
|
version "2.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/inline-style-prefixer/-/inline-style-prefixer-2.0.5.tgz#c153c7e88fd84fef5c602e95a8168b2770671fe7"
|
||||||
|
dependencies:
|
||||||
|
bowser "^1.0.0"
|
||||||
|
hyphenate-style-name "^1.0.1"
|
||||||
|
|
||||||
inquirer@^0.12.0:
|
inquirer@^0.12.0:
|
||||||
version "0.12.0"
|
version "0.12.0"
|
||||||
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e"
|
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e"
|
||||||
@ -7105,6 +7120,17 @@ react-sortable@^1.2.0:
|
|||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/react-sortable/-/react-sortable-1.2.0.tgz#5acd7e1910df665408957035acb5f2354519d849"
|
resolved "https://registry.yarnpkg.com/react-sortable/-/react-sortable-1.2.0.tgz#5acd7e1910df665408957035acb5f2354519d849"
|
||||||
|
|
||||||
|
react-split-pane:
|
||||||
|
version "0.1.57"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-split-pane/-/react-split-pane-0.1.57.tgz#7cc2d30841ae6a3e246ee613a9858012528d894f"
|
||||||
|
dependencies:
|
||||||
|
inline-style-prefixer "^2.0.4"
|
||||||
|
react-style-proptype "^1.4.0"
|
||||||
|
|
||||||
|
react-style-proptype@^1.4.0:
|
||||||
|
version "1.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-style-proptype/-/react-style-proptype-1.4.0.tgz#d82c4093b73767e3efaacba013cea22a50e7b5ee"
|
||||||
|
|
||||||
react-themeable@^1.1.0:
|
react-themeable@^1.1.0:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/react-themeable/-/react-themeable-1.1.0.tgz#7d4466dd9b2b5fa75058727825e9f152ba379a0e"
|
resolved "https://registry.yarnpkg.com/react-themeable/-/react-themeable-1.1.0.tgz#7d4466dd9b2b5fa75058727825e9f152ba379a0e"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user