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:
Cássio Souza 2016-12-12 19:23:52 -02:00 committed by GitHub
parent d6292bf4ff
commit 635049b8db
5 changed files with 158 additions and 66 deletions

View File

@ -135,6 +135,7 @@
"react-sidebar": "^2.2.1",
"react-simple-dnd": "^0.1.2",
"react-sortable": "^1.2.0",
"react-split-pane": "^0.1.57",
"react-toolbox": "^1.2.1",
"react-topbar-progress-indicator": "^1.0.0",
"react-waypoint": "^3.1.3",

View File

@ -4,34 +4,37 @@
}
.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 {
flex: 1;
height: calc(100% - 55px);
overflow: auto;
padding: 0 20px;
border-right: 1px solid var(--defaultColorLight);
}
.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;
}

View File

@ -1,59 +1,86 @@
import React, { PropTypes } from 'react';
import React, { Component, PropTypes } from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
import SplitPane from 'react-split-pane';
import { ScrollSync, ScrollSyncPane } from '../ScrollSync';
import ControlPane from '../ControlPanel/ControlPane';
import PreviewPane from '../PreviewPane/PreviewPane';
import Toolbar from './EntryEditorToolbar';
import styles from './EntryEditor.css';
export default function EntryEditor(
{
collection,
entry,
fields,
getMedia,
onChange,
onAddMedia,
onRemoveMedia,
onPersist,
onCancelEdit,
}) {
return (
<div className={styles.root}>
<ScrollSync>
<div className={styles.container}>
<ScrollSyncPane>
<div className={styles.controlPane}>
<ControlPane
collection={collection}
entry={entry}
fields={fields}
getMedia={getMedia}
onChange={onChange}
onAddMedia={onAddMedia}
onRemoveMedia={onRemoveMedia}
/>
</div>
</ScrollSyncPane>
<div className={styles.previewPane}>
<PreviewPane
collection={collection}
entry={entry}
fields={fields}
getMedia={getMedia}
/>
class EntryEditor extends Component {
state = {
showEventBlocker: false,
};
handleSplitPaneDragStart = () => {
this.setState({ showEventBlocker: true });
};
handleSplitPaneDragFinished = () => {
this.setState({ showEventBlocker: false });
};
render() {
const {
collection,
entry,
fields,
getMedia,
onChange,
onAddMedia,
onRemoveMedia,
onPersist,
onCancelEdit,
} = this.props;
const controlClassName = `${ styles.controlPane } ${ this.state.showEventBlocker && styles.blocker }`;
const previewClassName = `${ styles.previewPane } ${ this.state.showEventBlocker && styles.blocker }`;
return (
<div className={styles.root}>
<ScrollSync>
<div className={styles.container}>
<SplitPane
defaultSize="50%"
onDragStarted={this.handleSplitPaneDragStart}
onDragFinished={this.handleSplitPaneDragFinished}
>
<ScrollSyncPane>
<div className={controlClassName}>
<ControlPane
collection={collection}
entry={entry}
fields={fields}
getMedia={getMedia}
onChange={onChange}
onAddMedia={onAddMedia}
onRemoveMedia={onRemoveMedia}
/>
</div>
</ScrollSyncPane>
<div className={previewClassName}>
<PreviewPane
collection={collection}
entry={entry}
fields={fields}
getMedia={getMedia}
/>
</div>
</SplitPane>
</div>
</ ScrollSync>
<div className={styles.footer}>
<Toolbar
isPersisting={entry.get('isPersisting')}
onPersist={onPersist}
onCancelEdit={onCancelEdit}
/>
</div>
</ScrollSync>
<div className={styles.footer}>
<Toolbar
isPersisting={entry.get('isPersisting')}
onPersist={onPersist}
onCancelEdit={onCancelEdit}
/>
</div>
</div>
);
);
}
}
EntryEditor.propTypes = {
@ -67,3 +94,6 @@ EntryEditor.propTypes = {
onRemoveMedia: PropTypes.func.isRequired,
onCancelEdit: PropTypes.func.isRequired,
};
export default EntryEditor;

View File

@ -92,6 +92,38 @@ h1 {
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 {
position: relative;

View File

@ -1175,6 +1175,10 @@ boom@2.x.x:
dependencies:
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:
version "0.3.1"
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"
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:
version "0.4.13"
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"
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:
version "0.12.0"
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"
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:
version "1.1.0"
resolved "https://registry.yarnpkg.com/react-themeable/-/react-themeable-1.1.0.tgz#7d4466dd9b2b5fa75058727825e9f152ba379a0e"