# Modal

模态弹出框

## 案例演示

### Modal基本使用

---demo
```js
import { Button, Modal } from 'amos-framework';

class Demo extends Component {

  state = {
    visible: false
  };

  open = () => {
    this.setState({
      visible: true
    });
  }

  cancel = (e) => {
    console.log('cancel:', e);
    this.setState({
      visible: false
    });
  }

  render() {
    const { visible } = this.state;
    return (
      <div>
        <Button onClick={this.open}>新增</Button>
        <Modal
          header="基本模态框"
          visible={visible}
          noDefaultFooter
          onCancel={this.cancel}
          content={<div>内容区域...</div>}
        />
      </div>
    );
  }
}

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

### Modal禁用动画

通过设置 `disabledAnimate=true` 禁用弹窗体动画，通过设置 `overlayerTransitionName=null` 设置遮罩动画，可自行分别设置这两个参数查看效果。

---demo
```js
import { Button, Modal } from 'amos-framework';

class Demo extends Component {

  state = {
    visible: false
  };

  open = () => {
    this.setState({
      visible: true
    });
  }

  cancel = (e) => {
    console.log('cancel:', e);
    this.setState({
      visible: false
    });
  }

  render() {
    const { visible } = this.state;
    return (
      <div>
        <Button onClick={this.open}>新增</Button>
        <Modal
          header="基本模态框"
          visible={visible}
          noDefaultFooter
          onCancel={this.cancel}
          disabledAnimate
          overlayerTransitionName={null}
          content={<div>内容区域...</div>}
        />
      </div>
    );
  }
}

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

### Modal 设置内容区外层容器内联样式

通过设置 `contentStyle` 属性， 用于自定义 `content` 外层容器的自定义样式，如 `maxHeight、padding` 等

---demo
```js
import { Button, Modal } from 'amos-framework';

const body = (
  <div style={{ padding: 12 }}>
    {
      [...Array(12).keys()].map(i => <p key={i}>内容{i}...</p>)
    }
  </div>
);

class Demo extends Component {

  state = {
    visible: false
  };

  open = () => {
    this.setState({
      visible: true
    });
  }

  cancel = () => {
    this.setState({
      visible: false
    });
  }

  render() {
    const { visible } = this.state;
    return (
      <div>
        <Button onClick={this.open}>新增</Button>
        <Modal
          header="基本模态框"
          visible={visible}
          noDefaultFooter
          onCancel={this.cancel}
          contentStyle={{
            maxHeight: '200px',
            padding: 0
          }}
          content={body}
        />
      </div>
    );
  }
}

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

### Modal基本使用: drag
---demo
```js
import { Button, Modal } from 'amos-framework';

class Demo extends Component {

  state = {
    visible: false
  };

  open = () => {
    this.setState({
      visible: true
    });
  }

  cancel = () => {
    this.setState({
      visible: false
    });
  }

  render() {
    const { visible } = this.state;
    return (
      <div>
        <Button onClick={this.open}>新增</Button>
        <Modal
          header="可拖拽模态框"
          visible={visible}
          noDefaultFooter
          dragable
          onCancel={this.cancel}
          content={<div>内容区域...</div>}
        />
      </div>
    );
  }
}

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

### Modal基本使用: fullscreen

---demo
```js
import { Button, Modal } from 'amos-framework';

class Demo extends Component {

  state = {
    visible: false
  };

  open = () => {
    this.setState({
      visible: true
    });
  }

  cancel = () => {
    this.setState({
      visible: false
    });
  }

  render() {
    const { visible } = this.state;
    return (
      <div>
        <Button onClick={this.open}>新增</Button>
        <Modal
          header="全屏模态框"
          visible={visible}
          fullscreen
          onCancel={this.cancel}
          onOk={this.cancel}
          content={<div>内容区域...</div>}
        />
      </div>
    );
  }
}

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


### 切换全屏

---demo
```js
import { Button, Modal, Flex } from 'amos-framework';

class Demo extends Component {

  state = {
    visible: false,
    fullscreen: false
  };

  open = () => {
    this.setState({
      visible: true
    });
  }

  cancel = () => {
    this.setState({
      visible: false
    });
  }

  toggle = () => {
    this.setState((prevState) => {
      return {
        fullscreen: !prevState.fullscreen
      };
    });
  }

  renderHeader(){
    const { fullscreen } = this.state;
    return (
      <Flex justify="space-between" style={{ paddingRight: 18 }}>
        <span>可拖拽模态框</span>
        <Icon icon={fullscreen ? 'minus-square-o' : 'fullscreen'} onClick={this.toggle} />
      </Flex>
    );
  }

  render() {
    const { visible, fullscreen } = this.state;
    return (
      <Button onClick={this.open}>
        打开
        <Modal
          header={this.renderHeader()}
          visible={visible}
          fullscreen={fullscreen}
          noDefaultFooter
          destroyContent
          stopOuterBubble
          onCancel={this.cancel}
          content={<div>内容区域...</div>}
        />
      </Button>
    );
  }
}

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

### Modal自动调整top值

> 注意，如果设置 `fullscreen=true` 则不进行自动调整。

---demo
```js
import { Button, Modal } from 'amos-framework';

class Demo extends Component {

  state = {
    visible: false
  };

  open = () => {
    this.setState({
      visible: true
    });
  }

  cancel = () => {
    this.setState({
      visible: false
    });
  }

  render() {
    const { visible } = this.state;
    return (
      <div>
        <Button onClick={this.open}>打开</Button>
        <Modal
          header="弹窗"
          visible={visible}
          autoAdjustTop
          onCancel={this.cancel}
          content={<div>距离顶部的高度可自动调整...</div>}
        />
      </div>
    );
  }
}

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

### 打开另一个模态框（同级加载Modal）

---demo
```js
import { Button, Modal } from 'amos-framework';

class Demo extends Component {

  state = {
    visible: false,
    visible2: false
  };

  open = () => {
    this.setState({
      visible: true
    });
  }

  cancel = () => {
    this.setState({
      visible: false
    });
  }

  open2 = () => {
    this.setState({
      visible2: true
    });
  }

  cancel2 = () => {
    this.setState({
      visible2: false
    });
  }

  render() {
    const { visible, visible2 } = this.state;
    return (
      <div>
        <Button onClick={this.open}>打开</Button>
        <Modal
          header="模态框"
          visible={visible}
          noDefaultFooter
          onCancel={this.cancel}
          content={<div><Button onClick={this.open2}>打开另一个</Button>内容区域</div>}
        />
        <Modal
          header="子模态框"
          visible={visible2}
          noDefaultFooter
          onCancel={this.cancel2}
          content={<div>另一个 模态框内容</div>}
        />
      </div>
    );
  }
}

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

### 嵌套弹窗拖拽案例

注意，嵌套弹窗时，不建议两个弹窗均具备 draggable 特性，极限使用情况下，可参照下面这个案例，当打开第二个弹窗时，将第一个弹窗的 draggable 进行切换。
但是，此时会出现闪烁情况，why? 由于draggable 会改变弹窗内部的结构，因此动画会重新执行，从而出现闪烁。
解决办法：此时只需要给第一个弹窗设置 `disabledAnimate=true` 即可，强制禁用动画。

> 存在的问题：动态改变 draggable 时，会导致content重绘，此时，可采用 `dragableOps = { disabled: true }` 来禁用拖拽
> 嵌套的第二个弹窗可通过 `hiddenOverlayer=true` 来隐藏遮罩浮层，或者通过 `overlayerStyle` 设置自定义样式

---demo
```js
import { Button, Modal } from 'amos-framework';

class TestInner extends Component {
  constructor(props) {
    super(props);
    console.log('constructor：', 'TestInner');
  }
  render() {
    return <div>1</div>;
  }
}

class Demo extends Component {

  state = {
    disableDragfirst: false,
    visible: false,
    visible2: false
  };

  open = () => {
    this.setState({
      visible: true
    });
  }

  cancel = () => {
    this.setState({
      visible: false
    });
  }

  // 第二个弹窗打开之后，第一个弹窗的 drag 状态需要禁用，防止出现同时拖拽移动问题
  open2 = () => {
    this.setState({
      visible2: true,
      disableDragfirst: true
    });
  }

  cancel2 = () => {
    this.setState({
      visible2: false,
      disableDragfirst: false
    });
  }

  render() {
    const { visible, visible2, disableDragfirst } = this.state;
    return (
      <div>
        <Button onClick={this.open}>打开</Button>
        <Modal
          header="模态框"
          visible={visible}
          dragable
          dragableOps={disableDragfirst ? { disabled: true } : {}}
          disabledAnimate={disableDragfirst}
          noDefaultFooter
          destroyContent
          onCancel={this.cancel}
          content={
            <div>
              <Button onClick={this.open2}>打开另一个</Button>
              <div>内容区域</div>
              <TestInner />
              <Modal
                header="嵌套弹窗"
                dragable
                visible={visible2}
                noDefaultFooter
                overlayerStyle={{ backgroundColor: 'rgba(66, 81, 90, 0.1)' }}
                onCancel={this.cancel2}
                content={<div>另一个 模态框内容</div>}
              />
            </div>
          }
        />
      </div>
    );
  }
}

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

### Modal:禁止点击浮层关闭

---demo
```js
import { Button, Modal } from 'amos-framework';

class Demo extends Component {

  state = {
    visible: false
  };

  open = () => {
    this.setState({
      visible: true
    });
  }

  cancel = () => {
    this.setState({
      visible: false
    });
  }

  render() {
    const { visible } = this.state;
    return (
      <div>
        <Button onClick={this.open}>打开</Button>
        <Modal
          header="可拖拽模态框"
          visible={visible}
          noDefaultFooter
          destroyContent
          outterClosable={false}
          onCancel={this.cancel}
          content={<div>点击浮层，不能关闭...</div>}
        />
      </div>
    );
  }
}

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

### Modal:关闭时销毁内容
---demo
```js
import { Button, Modal } from 'amos-framework';

class Demo extends Component {

  state = {
    visible: false
  };

  open = () => {
    this.setState({
      visible: true
    });
  }

  cancel = () => {
    this.setState({
      visible: false
    });
  }

  render() {
    const { visible } = this.state;
    return (
      <div>
        <Button onClick={this.open}>打开</Button>
        <Modal
          header="可拖拽模态框"
          visible={visible}
          noDefaultFooter
          destroyContent
          onCancel={this.cancel}
          content={<div>内容区域...</div>}
        />
      </div>
    );
  }
}

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

### Modal:作为Button的子元素

需要设置 `stopOuterBubble` 为 `true` 否则，将会传递外层 click 事件至 `Button` 组件

---demo
```js
import { Button, Modal } from 'amos-framework';

class Demo extends Component {

  state = {
    visible: false
  };

  open = () => {
    this.setState({
      visible: true
    });
  }

  cancel = () => {
    this.setState({
      visible: false
    });
  }

  render() {
    const { visible } = this.state;
    return (
      <Button onClick={this.open}>
        打开
        <Modal
          header="可拖拽模态框"
          visible={visible}
          noDefaultFooter
          destroyContent
          stopOuterBubble
          onCancel={this.cancel}
          content={<div>内容区域...</div>}
        />
      </Button>
    );
  }
}

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

### Modal 综合使用

---demo
```js
import { Button, Modal, Select } from 'amos-framework';

const Option = Select.Option;

class Demo extends Component {

  state = {
    visible: false
  };

  open = () => {
    this.setState({
      visible: true
    });
  }

  cancel = () => {
    this.setState({
      visible: false
    });
  }

  renderContent(){
    return (
      <div>
        <Select defaultValue="1">
          <Option>请选择</Option>
          <Option value="0">张三</Option>
          <Option value="1">李四</Option>
          <Option value="2">王五</Option>
        </Select>
      </div>
    );
  }

  render() {
    const { visible } = this.state;
    const content = this.renderContent();
    return (
      <div>
        <Button onClick={this.open}>打开</Button>
        <Modal
          header="组合使用"
          visible={visible}
          noDefaultFooter
          destroyContent
          onCancel={this.cancel}
          content={content}
        />
      </div>
    );
  }
}

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

### Modal 遮罩内容高斯模糊

---demo
```js
import { Button, Modal } from 'amos-framework';

const ButtonGroup = Button.Group;

const mapping = {
  no: false,
  basic: true,
  deep: { strength: 5 },
  deep2: { strength: 10 }
};

class Demo extends Component {

  state = {
    visible: false,
    frostedProps: true
  };

  open = () => {
    this.setState({
      visible: true
    });
  }

  cancel = () => {
    this.setState({
      visible: false
    });
  }

  handleChange = (value) => {
    this.setState({
      frostedProps: mapping[value]
    });
  }

  render() {
    const { visible, frostedProps } = this.state;
    return (
      <div>
        选择高斯模糊级别：
        <ButtonGroup defaultValue="basic" onChange={this.handleChange}>
          <Button value="no">无</Button>
          <Button value="basic">默认</Button>
          <Button value="deep">强度1</Button>
          <Button value="deep2">强度2</Button>
        </ButtonGroup>
        <div style={{ marginTop: 15 }}>
          <Button onClick={this.open}>打开弹出框</Button>
        </div>
        <Modal
          header="基本模态框"
          visible={visible}
          noDefaultFooter
          frostedProps={frostedProps}
          onCancel={this.cancel}
          content={<div>内容区域...</div>}
        />
      </div>
    );
  }
}

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

### Modal: 信息提示框

---demo
```js
import { Button, Modal, Paragraph } from 'amos-framework';

function openConfirm(type){
  if (type === 'confirm'){
    Modal.confirm({
      title: '是否删除',
      content: '是否删除?',
      onOk() {
        // 执行删除逻辑
      },
      onCancel() {}
    });
  } else {
    Modal[type]({
      title: `open ${type} message`,
      content: '我是内容区'
    });
  }
}

const delayClose = () => {
  Modal.confirm({
    title: '删除？',
    content: '点击确定之后，延迟1秒关闭',
    onOk() {
      return new Promise((resolve, reject) => {
        setTimeout(Math.random() > 0.5 ? resolve : reject, 1000);
      }).catch(() => console.log('delay close errors!'));
    },
    onCancel() {}
  });
}

const autoClose = () => {
  const modal = Modal.error({
    title: '警告',
    content: '前方高能，请注意！（3秒后自动消失）'
  });

  setTimeout(() => modal.destroy(), 3000);
}

function openCusInfo(){
  Modal.info({
    title: 'open 自定义 html 字符串 message',
    // content: <Paragraph html="<div style='color: red;'>内容<strong>强调</strong></div>" />
    content: <Paragraph html="<span style='color: red;'>内容1<br />内容2<br />内容3<br /></span>" />
  });
}

ReactDOM.render(
  <div className="btn-demo">
    <Button onClick={() => openConfirm('info')}>info</Button>
    <Button onClick={() => openConfirm('success')}>success</Button>
    <Button onClick={() => openConfirm('error')}>error</Button>
    <Button onClick={() => openConfirm('warning')}>warning</Button>
    <Button onClick={() => openConfirm('warn')}>warn</Button>
    <Button onClick={() => openConfirm('confirm')}>confirm</Button>
    <Button onClick={() => openCusInfo('')}>自定义html内容</Button>
    <Button onClick={delayClose}>延迟关闭</Button>
    <Button onClick={autoClose}>自动关闭</Button>
  </div>
  , _react_runner_);
```
---demoend

### Modal全局弹出框

全局任意位置弹出窗，采用执行方法的方式唤醒弹出框。`ghost['alert|show']` 仅支持通过 `full=true` 设置全屏。

---demo
```js
import { Button, Modal, Icon, Flex } from 'amos-framework';

const ghost = Modal.ghost;
const LoadingButton = Button.LoadingButton;

function repeat3(msg){
  return `${msg} `.repeat(3) + '......';
}

const popupAlert = () => {
  ghost.alert({
    title: 'Alert',
    content: repeat3('alert content'),
    onOk: () => console.log('ok')
  });
};

const popupCustom = () => {
  const dialog = ghost.show({
    title: 'Custom',
    content: repeat3('custom content'),
    footer: (
      <Button type="minor" onClick={() => dialog.hide()}>
        Custom button
      </Button>
    )
  });
};

const popupCustom2 = () => {
  const dialog = ghost.show({
    title: '标题',
    content: '自定义显示动画...',
    transitionName: 'plop',
    footer: (
      <Button type="minor" onClick={() => dialog.hide()}>
        自定义动画
      </Button>
    )
  });
};

// 可进行拖拽的 ghost modal
const popupCustom3 = () => {
  const _dragStyle = {
    background: '#eee',
    padding: '6px',
    border: '1px solid red',
    cursor: 'move'
  };
  const dialog = ghost.show({
    title: (
      <div style={_dragStyle} className="my-ghost-dialog">
        标题区域
      </div>
    ),
    content: '这是内容区...',
    dragable: true,
    // 该项必须设置为 false，因为 ghost.show 无 header
    onlyDragheader: false,
    // 设置自定义的拖拽项，如果任何区域均可拖拽，则无需设置
    dragableOps: {
      // 设置可拖拽的区域 （css 选择器）
      handle: '.my-ghost-dialog'
    },
    footer: (
      <Button type="minor" onClick={() => dialog.hide()}>
        关闭
      </Button>
    )
  });
};

const popupFullCustom = () => {
  const dialog = ghost.alert({
    title: 'Custom',
    content: '自定义弹框，全屏模式...',
    full: true,
    footer: (
      <Button type="minor" onClick={() => dialog.hide()}>
        关闭
      </Button>
    )
  });
};

const popupFullCustom2 = () => {
  const dialog = ghost.alert({
    title: (
      <Flex justify="space-between">
        <div>自定义标题</div>
        <Flex className="amos-modal-header-btns" gap={8}>
          <span className="amos-modal-max" onClick={() => dialog.full(!dialog.state('full'))}>
            <Icon icon="rect" />
          </span>
          <span className="amos-modal-closer" onClick={() => dialog.hide()}>
            <Icon icon="cancel" />
          </span>
        </Flex>
      </Flex>
    ),
    content: '自定义弹框，全屏模式,可自由切换状态...',
    full: false, // 初始状态为非全屏
    footer: (
      <Button type="minor" onClick={() => dialog.hide()}>
        关闭
      </Button>
    )
  });
};

const postCustom = () => {
  const dialog = ghost.show({
    title: 'Custom',
    content: '表单提交...',
    footer({ loading, onOk }) {
      return (
        <LoadingButton loading={loading} onClick={onOk} style={{ width: '150px' }}>
          {loading ? '正在提交...' : '提交'}
        </LoadingButton>
      );
    },
    onOk: () => {
      return new Promise(resolve => {
          // 模拟提交
          setTimeout(resolve, 2000);
        }).then(() => {
          // 完成
          dialog.hide();
        });
      }
  });
};

ReactDOM.render(
  <div className="btn-demo">
    <Button onClick={popupAlert}>Alert</Button> &nbsp;
    <Button onClick={popupCustom}>自定义</Button>
    <Button onClick={popupCustom2}>自定义动画</Button>
    <Button onClick={popupFullCustom}>全屏</Button>
    <Button onClick={popupFullCustom2}>全屏切换</Button>
    <Button onClick={postCustom}>表单提交</Button>
    <Button onClick={popupCustom3}>可拖拽的</Button>
  </div>
  , _react_runner_);
```
---demoend

### Modal全局弹出框 - 启用动画和拖拽

---demo
```js
import { Button, Modal } from 'amos-framework';

const ghost = Modal.ghost;

// 可进行拖拽的 ghost modal
const popupCustom3 = () => {
  const _dragStyle = {
    background: '#eee',
    padding: '6px',
    border: '1px solid red',
    cursor: 'move'
  };
  const dialog = ghost.show({
    title: (
      <div style={_dragStyle} className="my-ghost-dialog">
        标题区域
      </div>
    ),
    content: '这是内容区...',
    afterClose(){
      // 测试关闭后的输出
      console.log('ghost.show: afterClose');
    },
    // 外部手动执行的关闭 cancel
    onCancel(e){
      console.log('ghost.show: onCancel', e);
      // return new Promise((resolve, reject) => {
      //   resolve();
      // });
    },
    // 内部执行关闭之后，同步外部的关闭，注意与 `onCancel` 区别
    onClose(e){
      console.log('ghost.show: onClose', e);
      // return new Promise((resolve, reject) => {
      //   resolve();
      // });
    },
    dragable: true,
    // 该项必须设置为 false，因为 ghost.show 无 header
    onlyDragheader: false,
    // 设置自定义的拖拽项，如果任何区域均可拖拽，则无需设置
    dragableOps: {
      // 设置可拖拽的区域 （css 选择器）
      handle: '.my-ghost-dialog'
    },
    // 注意，该方式不回触发 onCancel 和 onClose
    // footer: (
    //   <Button type="minor" onClick={() => dialog.hide()}>
    //     关闭
    //   </Button>
    // )
    footer({ loading, onOk, onCancel }){
      return (
        <div>
          <Button type="minor" onClick={onCancel}>onCancel关闭</Button>
          <Button type="minor" onClick={() => dialog.hide()}>hide关闭</Button>
        </div>
      );
    }
  });
};

ReactDOM.render(
  <div className="btn-demo">
    <Button onClick={popupCustom3}>可拖拽的</Button>
  </div>
  , _react_runner_);
```
---demoend


### 测试 body 缩放对居中的影响

手动给 body 设置 `zoom: 0.66`

---demo
```js
import { Button, Modal } from 'amos-framework';

class Demo extends Component {

  state = {
    visible: false
  };

  open = () => {
    this.setState({
      visible: true
    });
  }

  cancel = (e) => {
    console.log('cancel:', e);
    this.setState({
      visible: false
    });
  }

  render() {
    const { visible } = this.state;
    return (
      <div>
        <Button onClick={this.open}>新增</Button>
        <Modal
          header="基本模态框"
          width={1903}
          visible={visible}
          noDefaultFooter
          onCancel={this.cancel}
          content={<div>内容区域...</div>}
        />
      </div>
    );
  }
}

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

## props

| params  | type | default | description |
| --- | --- | --- | --- |
| prefixCls | string | `amos-modal` | css class 前缀 |
| className | string | - | css class |
| wrapClassName | string | - | 最外层 wrap div 的 css class |
| header | ReactNode | - | 对话框标题 |
| content | ReactNode | - | 对话框内容 |
| footer | ReactNode | `确定取消按钮` | 自定义footer |
| onCancel | function(e) | 无 | 点击遮罩层或右上角叉或取消按钮的回调。如果按 `ESC` 关闭时，则参数为`undefined` |
| onOk | function(e) | 无 | 点击确定回调 |
| closable | boolean | true | 是否显示右上角的关闭按钮 |
| closerContent | ReactNode | - | 当 closable 为 true 时，可自定义 closerContent 内容。如果传入的是 react 组件，则需要自行处理 close 事件 |
| outterClosable | boolean | true | 点击蒙层是否允许关闭 |
| width | `string、number` | 560 | 宽度 |
| dragable | boolean | false | 是否可拖拽 |
| dragableOps | object | [DragOptions](#DragOptions) | 拖拽参数 |
| onlyDragheader | boolean | true | 仅支持 header 进行拖拽 |
| transitionName | string | zoom | 弹出框显隐动画名称 |
| animation | string | - | 动画后缀名 |
| visible | boolean | 无 | 对话框显隐，true时，显示 |
| afterClose | function | 无 | Modal 完全关闭后的回调 |
| okText | string | 确定 | 确认按钮文字 |
| cancelText | string | 取消 | 取消按钮文字 |
| noDefaultFooter | boolean | - | 禁用默认footer |
| noDefaultHeader | boolean | - | 禁用默认header，设置为true时，不显示右上角的关闭，则还需设置 `closable=false` |
| destroyContent | boolean | - | 关闭时从dom上销毁内容 |
| stopOuterBubble | boolean | - | 阻止外层元素时间冒泡，当 Modal 作为 Button 等可接收 onClick 事件的组件时，需要设置为true来阻止外层容器的click事件 |
| overlayerTransitionName | string | fade | 遮罩层过度动画，设置为 null 或者 false 以禁用过度动效 |
| hiddenOverlayer | boolean | - | 隐藏遮罩 |
| frostedProps | `Object: { targetId, strength } or true、null、false` | - | 弹框背景遮罩层启用高斯模糊。可以直接设置为true，则将 `#app` 节点启用高斯模糊。 |
| fullscreen | boolean | - | 全屏，浏览器全屏 |
| contentStyle | Object | - | content 内容区外层 div 的自定义内联样式，使用场景：`设置自定义的最大高度、padding 等`, since v1.8.2 |
| rootVarStyle | Object | - | 根节点存放 css 变量，仅用于设置自定义的 `css` 变量样式，since v1.9.8 |
| autoAdjustTop | boolean | - | 自动调整 modal 距离顶部位置 |
| disabledAnimate | boolean | - | 禁用弹窗打开关闭时的动画，since v1.11.7，使用场景：多弹窗嵌套+弹窗拖拽，详细可看案例 [嵌套弹窗拖拽案例](#嵌套弹窗拖拽案例) |
| overlayerStyle | Object | - | 遮罩层自定义样式 |
| disableShaked | boolean | - | 禁用点击蒙层不关闭时的抖动效果 |

> `frostedProps` 为 object 对象时，属性键 `targetId` 仅支持指定的元素的 `id` 选择器，默认为 `app` 节点。可以通过设置 `true` 使用系统内置的高斯模糊配置，
> 属性键 `strength` 为高斯强度，建议 `1~10`。注意：高斯模糊，采用 `filter: blur(px)` 属性进行设置，请确保浏览器支持该属性。

> 注意：动态改变 dragable 会导致 content 重新加载

> 设置 `disabledAnimate=true` 时，会去掉动画过程，原理：设置 Animate 的 `showProp=null` 来禁用动画过程。

### DragOptions

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

### Method

- `Modal.info`
- `Modal.success`
- `Modal.error`
- `Modal.warning | Modal.warn`
- `Modal.confirm`

参数说明：

```js
 const config = {
  title: `string or ReactNode`, //
  content: `string or ReactNode`, //
  okCancel: `boolean`, // true 时，显示 `ok` 与 `cancel，` 否则只显示 `ok`
  onCancel: ``, // 取消回调，参数为关闭函数，返回 promise 时 resolve 后自动关闭
  onOk: ``, // 点击确定回调，参数为关闭函数，返回 promise 时 resolve 后自动关闭
  okText: ``, // 确认按钮文字
  cancelText: ``,// 取消按钮文字
  width:``, // 宽度
  style: ``, // 外层style样式
  useInnerIcon: true, // 是否启用内置 icon 组件，默认为 true
  icon: `` // 图标
}
```

返回值是一个modal 引用，可以调用 `destroy()`进行关闭

```js
const error = Modal.error();

error.destroy();
```

### Modal.ghost 全局弹框

since v 1.3.0 新增全局弹框，[使用教程](#Modal全局弹出框)

提供两种方法进行唤醒弹框：

* `Modal.ghost.alert(): { hide: Function }`
* `Modal.ghost.show(): { hide: Function }`

全局弹窗关闭时，触发的事件说明：

* footer 采用 `dialog.hide()` 关闭，进会触发 `afterClose`
* fotter 采用 `function({ onCancel }){}` 方式，采用 `onCancel()` 关闭，触发 `onCancel、afterClose`
* `ESC` 键关闭，触发 `onClose、afterClose`
* `弹框外部区域` 关闭，触发 `onClose、afterClose`


```js
import { Button, Modal } from 'amos-framework';

const ghost = Modal.ghost;

ghost.alert({
  title: '',
  content: ''
});

ghost.show();
```

参数说明：

```js
 const config = {
  title: `string or ReactNode`, //
  content: `string or ReactNode`, //
  okCancel: `boolean`, // true 时，显示 `ok` 与 `cancel，` 否则只显示 `ok`
  onCancel: ``, // 取消回调，参数为关闭函数，返回 promise 时 resolve 后自动关闭
  onOk: ``, // 点击确定回调，参数为关闭函数，返回 promise 时 resolve 后自动关闭
  okText: ``, // 确认按钮文字
  cancelText: ``,// 取消按钮文字
  width:``, // 宽度
  style: ``, // 外层style样式
  // 自定义 footer，当为function时，需要返回ReactNode，参数为 { loading, onOk, onCancel }
  // 可通过 设置 footer=null,禁用，或者 `footer: () => null` 方式禁用
  footer: `function or ReactNode`,
  full: bool, // 是否为全屏
  transitionName: '', // 自定义过度动画，可参照 Animate 中定义的动画
  ... // 更多参数，可参照 Modal props
}
```

### 完整 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
}
```
