# MovablePane

## 何时使用

直接将内容渲染至具体的dom节点时使用，并且支持手动拖拽移动pane

> 注意，该案例页面，如果路由切换时，组件并未销毁，此时演示组件功能，请刷新后重试。

注意同 [SidePane](/framework/sidepane) 进行比较

## 案例演示

### 基本使用

---demo
```js
import { StdForm, MovablePane, Switch } from 'amos-framework';

class Demo extends Component {

  constructor(props) {
    super(props);
    this.state = {
      visible: true,
      dragable: false,
      onlyDragheader: false,
      animateDelay: 0
    };
  }

  onChange = (onOff) => {
    this.setState({
      visible: onOff
    });
  }

  onDragableChange = (onOff) => {
    this.setState({
      dragable: onOff
    });
  }

  onDelayChange = (value) => {
    this.setState({
      animateDelay: value
    });
  }

  genHandle = (type) => {
    return function(value){
      this.setState({
        [type]: value
      });
    }.bind(this);
  }

  render() {
    const { visible, animateDelay, dragable, onlyDragheader } = this.state;
    const animateProps = {
      transitionAppear: true
    };
    return (
      <div style={{ width: '25em', display: 'inline-block' }}>
        <StdForm label="延时">
          <InputNumber value={animateDelay} type="outer" min={0} max={10} onChange={this.onDelayChange} />
        </StdForm>
        <StdForm label="显示/隐藏">
          <Switch onOff={visible} onChange={this.onChange} />
        </StdForm>
        <StdForm label="移动">
          <Switch onOff={dragable} onChange={this.onDragableChange} />
        </StdForm>
        <StdForm label="开启header移动">
          <Switch onOff={onlyDragheader} onChange={this.genHandle('onlyDragheader')} />
        </StdForm>
        <MovablePane
          left={10}
          top={50}
          visible={visible}
          dragable={dragable}
          onlyDragheader={onlyDragheader}
          title="可移动面板"
        >
          <ul style={{ background: '#ccc', padding: '2em' }}>
            <li>列表1</li>
            <li>列表2</li>
            <li>列表3</li>
            <li>列表4</li>
            <li>列表5</li>
          </ul>
        </MovablePane>
      </div>
    );
  }
}

ReactDOM.render(<Demo />, _react_runner_);
```
---demoend

## props

| params | type | default | description |
|--------- |-------- |--------- |-------- |
| prefixCls | string | `amos-sidepane` | 组件默认clssname prefix |
| className | string | - | 组件自定义clssname |
| style | object | {} | 组件自定义样式 |
| left | number or false | 10 | 至屏幕左侧距离，设置为false，则可以取消left设置 |
| top | number or false | 64 | 至屏幕顶部距离，设置为false，则可以取消top设置 |
| right | number or false | 64 | 至屏幕右侧距离，设置为false，则可以取消right设置 |
| bottom | number or false | 64 | 至屏幕底部距离，设置为false，则可以取消bottom设置 |
| children | ReactNode | - | 需要渲染的具体节点 |
| beforeRemove | func | - | 卸载dom之前执行 |
| getContainer | func | - | 获取自定义渲染目标dom，默认为：在body下创建一个div |
| animateName | string | - | 动画名称，具体支持的值，详见 [Animate](/#/framework/animate) |
| animateProps | object | - | 动画参数，详见组件 [Animate](/#/framework/animate) |
| visible | boolean | - | 控制 Pane 的显隐 |
| animateDelay | number | - | 开启动画渲染时，设置动画延迟执行时间，单位为 `s` |
| dragable | boolean | - | 是否开启拖拽模式 |
| onlyDragheader | boolean | - | 仅支持拖拽 header |
| dragableOps | object | [DragOptions](#DragOptions) | 拖拽参数配置 |

> 独立设置 `left、top、right、bottom` 将会覆盖 `style` 中的相应值，应用到界面中，单位为 `px`。

### DragOptions

```js
const _dragableOps = {
  axis: 'both', // both | x | y | none
  defaultPosition: { x: 0, y: 0 },
  position: null,
  // grid: [25, 25],
  zIndex: 99,
  bounds: 'body'
};
```

### 完整 dragableOps

```js
{
  // If set to `true`, will allow dragging on non left-button clicks.
  allowAnyClick: boolean,

  // Determines which axis the draggable can move. This only affects
  // flushing to the DOM. Callbacks will still include all values.
  // Accepted values:
  // - `both` allows movement horizontally and vertically (default).
  // - `x` limits movement to horizontal axis.
  // - `y` limits movement to vertical axis.
  // - 'none' stops all movement.
  axis: string,

  // Specifies movement boundaries. Accepted values:
  // - `parent` restricts movement within the node's offsetParent
  //    (nearest node with position relative or absolute), or
  // - a selector, restricts movement within the targeted node
  // - An object with `left, top, right, and bottom` properties.
  //   These indicate how far in each direction the draggable
  //   can be moved.
  bounds: {left: number, top: number, right: number, bottom: number} | string,

  // Specifies a selector to be used to prevent drag initialization.
  // Example: '.body'
  cancel: string,

  // Class names for draggable UI.
  // Default to 'react-draggable', 'react-draggable-dragging', and 'react-draggable-dragged'
  defaultClassName: string,
  defaultClassNameDragging: string,
  defaultClassNameDragged: string,

  // Specifies the `x` and `y` that the dragged item should start at.
  // This is generally not necessary to use (you can use absolute or relative
  // positioning of the child directly), but can be helpful for uniformity in
  // your callbacks and with css transforms.
  defaultPosition: {x: number, y: number},

  // If true, will not call any drag handlers.
  disabled: boolean,

  // Specifies the x and y that dragging should snap to.
  grid: [number, number],

  // Specifies a selector to be used as the handle that initiates drag.
  // Example: '.handle'
  handle: string,

  // If desired, you can provide your own offsetParent for drag calculations.
  // By default, we use the Draggable's offsetParent. This can be useful for elements
  // with odd display types or floats.
  offsetParent: HTMLElement,

  // Called whenever the user mouses down. Called regardless of handle or
  // disabled status.
  onMouseDown: (e: MouseEvent) => void,

  // Called when dragging starts. If `false` is returned any handler,
  // the action will cancel.
  onStart: DraggableEventHandler,

  // Called while dragging.
  onDrag: DraggableEventHandler,

  // Called when dragging stops.
  onStop: DraggableEventHandler,

  // Much like React form elements, if this property is present, the item
  // becomes 'controlled' and is not responsive to user input. Use `position`
  // if you need to have direct control of the element.
  position: {x: number, y: number}

  // A position offset to start with. Useful for giving an initial position
  // to the element. Differs from `defaultPosition` in that it does not
  // affect the postiion returned in draggable callbacks, and in that it
  // accepts strings, like `{x: '10%', y: '10%'}`.
  positionOffset: {x: number | string, y: number | string},

  // Specifies the scale of the canvas your are dragging this element on. This allows
  // you to, for example, get the correct drag deltas while you are zoomed in or out via
  // a transform or matrix in the parent of this element.
  scale: number
}
```
