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-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",

View File

@ -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;
} }

View File

@ -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;

View File

@ -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;

View File

@ -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"