diff --git a/src/common/util.js b/src/common/util.js
index 2126f3d45..9ab1294bc 100644
--- a/src/common/util.js
+++ b/src/common/util.js
@@ -245,6 +245,12 @@ module.exports = {
context[method] = (...args) =>
refinement.call(context, args, original.apply(context, args))
+ },
+
+ restrict(value, lower, upper) {
+ value = Math.max(value, (lower != null) ? lower : value)
+ value = Math.min(value, (upper != null) ? upper : value)
+ return value
}
}
diff --git a/src/components/panel.js b/src/components/panel.js
index 5259f4512..e04b406c1 100644
--- a/src/components/panel.js
+++ b/src/components/panel.js
@@ -57,7 +57,7 @@ const PanelGroup = ({ header, children, height }) => {
{panels.map((panel, idx) => (
-
+
{panel}
))}
diff --git a/src/components/resizable.js b/src/components/resizable.js
index 00e0e6ca4..a2569859e 100644
--- a/src/components/resizable.js
+++ b/src/components/resizable.js
@@ -1,9 +1,13 @@
'use strict'
const React = require('react')
-const { PropTypes } = React
-const { Shapes } = require('./util')
-const cn = require('classnames')
+const { PureComponent, PropTypes } = React
+const { func, node, bool, number, oneOf } = PropTypes
+const cx = require('classnames')
+const { bounds, on, off } = require('../dom')
+const { restrict } = require('../common/util')
+const { keys } = Object
+
const DIR = {
top: 'row', right: 'col', bottom: 'row', left: 'col'
@@ -13,36 +17,132 @@ const DIM = {
top: 'height', right: 'width', bottom: 'height', left: 'width'
}
+const OPP = {
+ top: 'bottom', right: 'left', bottom: 'top', left: 'right'
+}
-const ResizableHandle = ({ edge }) => (
-
-)
-
-ResizableHandle.propTypes = {
- edge: Shapes.edge.isRequired
+const AXS = {
+ top: 'pageY', right: 'pageX', bottom: 'pageY', left: 'pageX'
}
-const Resizable = ({ value, children, edge, relative }) => (
-
- {children}
-
-
-)
-
-Resizable.propTypes = {
- children: PropTypes.node,
- edge: Shapes.edge.isRequired,
- relative: PropTypes.bool,
- value: PropTypes.number.isRequired
+class Resizable extends PureComponent {
+ constructor(props) {
+ super(props)
+
+ this.state = {
+ value: props.value,
+ isDragging: false
+ }
+ }
+
+ componentWillUnmount() {
+ if (this.state.isDragging) {
+ this.stop()
+ }
+ }
+
+ componentWillReceiveProps(props) {
+ this.setState({ value: props.value })
+ }
+
+ get dimension() {
+ return DIM[this.props.edge]
+ }
+
+ get value() {
+ return `${this.state.value}${this.props.isRelative ? '%' : 'px'}`
+ }
+
+ get style() {
+ return {
+ [this.dimension]: this.value
+ }
+ }
+
+ handleMouseDown = () => {
+ this.start()
+ }
+
+ setContainer = (container) => {
+ this.container = container
+ }
+
+ update = (event) => {
+ const { edge, min, max } = this.props
+
+ const origin = bounds(this.container)[OPP[edge]]
+ const value = restrict(event[AXS[edge]] - origin, min, max)
+
+ this.setState({ value })
+ }
+
+ start() {
+ this.setState({ isDragging: true })
+
+ on(document, 'mousemove', this.update)
+ on(document, 'mouseup', this.stop, { capture: true })
+ on(document, 'mouseleave', this.stop)
+ on(window, 'blur', this.stop)
+ }
+
+ stop = () => {
+ this.setState({ isDragging: false })
+
+ off(document, 'mousemove', this.update)
+ off(document, 'mouseup', this.stop, { capture: true })
+ off(document, 'mouseleave', this.stop)
+ off(window, 'blur', this.stop)
+
+ if (this.props.value !== this.state.value) {
+ //this.props.onResize(value)
+ //console.log('resize', this.state.value)
+ }
+ }
+
+
+ renderHandle() {
+ const { edge, isDisabled } = this.props
+
+ return !isDisabled && (
+
+ )
+ }
+
+ render() {
+ return (
+
+ {this.props.children}
+ {this.renderHandle()}
+
+ )
+ }
+
+ static propTypes = {
+ children: node,
+ edge: oneOf(keys(DIM)).isRequired,
+ isDisabled: bool,
+ isRelative: bool,
+ value: number.isRequired,
+ min: number,
+ max: number,
+ onResize: func //.isRequired
+ }
+
+ static defaultProps = {
+ min: 0
+ }
}
+
module.exports = {
- Resizable,
- ResizableHandle
+ Resizable
}
diff --git a/src/components/slider.js b/src/components/slider.js
index b02d11f3d..566dc1fe6 100644
--- a/src/components/slider.js
+++ b/src/components/slider.js
@@ -5,8 +5,9 @@ const { PureComponent, PropTypes } = React
const { IconButton } = require('./button')
const cx = require('classnames')
const { bounds, borders, on, off } = require('../dom')
-const { noop } = require('../common/util')
+const { restrict } = require('../common/util')
const { bool, element, func, number, oneOf } = PropTypes
+const { round } = Math
class Slider extends PureComponent {
@@ -20,7 +21,7 @@ class Slider extends PureComponent {
componentWillReceiveProps({ value }) {
if (value !== this.props.value &&
- value !== Math.round(this.state.value)) {
+ value !== round(this.state.value)) {
this.setState({ value })
}
}
@@ -44,7 +45,7 @@ class Slider extends PureComponent {
const left = box.left + border.left
const width = box.width - border.left - border.right
- this.set(min + restrict((event.pageX - left) / width) * max)
+ this.set(min + restrict((event.pageX - left) / width, 0, 1) * max)
}
handleMouseDown = ({ button, pageX }) => {
@@ -54,21 +55,10 @@ class Slider extends PureComponent {
this.startDragging()
}
- handleMouseUp = (event) => {
- try {
- if (event instanceof MouseEvent) {
- this.update(event)
- }
-
- } finally {
- this.stopDragging()
- }
- }
-
set = (value) => {
this.setState({ value })
- const nearest = Math.round(value)
+ const nearest = round(value)
if (nearest !== this.props.value) {
this.props.onChange(nearest)
@@ -106,18 +96,18 @@ class Slider extends PureComponent {
this.setState({ isDragging: true })
on(document, 'mousemove', this.update)
- on(document, 'mouseup', this.handleMouseUp, { capture: true })
+ on(document, 'mouseup', this.stopDragging, { capture: true })
on(document, 'mouseleave', this.stopDragging)
- on(window, 'blur', this.handleMouseUp)
+ on(window, 'blur', this.stopDragging)
}
stopDragging = () => {
this.setState({ isDragging: false })
off(document, 'mousemove', this.update)
- off(document, 'mouseup', this.handleMouseUp, { capture: true })
+ off(document, 'mouseup', this.stopDragging, { capture: true })
off(document, 'mouseleave', this.stopDragging)
- off(window, 'blur', this.handleMouseUp)
+ off(window, 'blur', this.stopDragging)
if (this.delayed) {
clearTimeout(this.delayed)
@@ -197,15 +187,10 @@ class Slider extends PureComponent {
static defaultProps = {
min: 0,
max: 1,
- size: 'md',
- onChange: noop
+ size: 'md'
}
}
-function restrict(value, lower = 0, upper = 1) {
- return Math.min(Math.max(value, lower), upper)
-}
-
module.exports = {
Slider
}
diff --git a/src/components/util.js b/src/components/util.js
index 378344a3f..3c4c9af6f 100644
--- a/src/components/util.js
+++ b/src/components/util.js
@@ -1,7 +1,7 @@
'use strict'
const {
- Children, PropTypes, PureComponent, createElement: create
+ Children, PureComponent, createElement: create
} = require('react')
const { diff } = require('../common/util')
@@ -86,8 +86,6 @@ module.exports = {
},
Shapes: {
- edge: PropTypes.oneOf(['top', 'right', 'bottom', 'left']),
-
number(min, max, required = true) {
return (props, name, component) => {
const value = props[name]