# @eightfeet/modal

> 弹窗模块，需要promise polyfill demo

Latest version **2.2.30** (published 2022-05-26) · ISC license · 0 weekly downloads

## Install

```sh
npm install @eightfeet/modal
pnpm add @eightfeet/modal
yarn add @eightfeet/modal
bun add @eightfeet/modal
```

## Health

**Score 20/100 (F)** — status: abandoned.

Positive: has types; no vulnerabilities.

Warnings: low downloads; no esm support.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 2.2.30 |
| Published | 2022-05-26 |
| First published | 2019-02-16 |
| Weekly downloads | 0 |
| License | ISC |
| TypeScript types | bundled |
| Module format | CommonJS |
| Dependencies | 6 |
| Unpacked size | 68 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 0 |
| Author | eightfeet |
| Maintainers | eightfeet |

## Links

- npm: https://www.npmjs.com/package/@eightfeet/modal
- Repository: https://github.com/eightfeet/Modalv2
- Homepage: https://github.com/eightfeet/Modalv2#readme
- Issues: https://github.com/eightfeet/Modalv2/issues
- npm.io page: https://npm.io/package/@eightfeet/modal

## Dependencies (6)

- [mime](https://npm.io/package/mime.md) ^2.3.1
- [core-js](https://npm.io/package/core-js.md) ^3.2.1
- [csstype](https://npm.io/package/csstype.md) ^3.0.4
- [@babel/runtime](https://npm.io/package/@babel/runtime.md) ^7.1.2
- [css-in-js-utils](https://npm.io/package/css-in-js-utils.md) ^3.1.0
- [inline-style-prefixer](https://npm.io/package/inline-style-prefixer.md) ^6.0.0

## Recent versions

- 2.2.30 (latest) — 2022-05-26
- 2.2.29 — 2022-05-11
- 2.2.28 — 2022-05-10
- 2.2.27 — 2022-04-20
- 2.2.26 — 2022-04-15
- 2.2.25 — 2022-04-15
- 2.2.24 — 2021-12-14
- 2.2.23 — 2021-07-28
- 2.2.21 — 2021-07-28
- 2.2.20 — 2021-07-24
- 2.2.19 — 2021-07-24
- 2.2.18 — 2021-04-29
- 2.2.17 — 2021-04-29
- 2.2.16 — 2021-03-18
- 2.2.15 — 2021-03-17
- … 53 more at https://npm.io/package/@eightfeet/modal/versions

## README

# modal

弹窗模块，需要promise polyfill
<a href="http://www.eightfeet.cn/ModalV2/lib/index.html" traget="_blank" >demo</a>

```sh
npm i @eightfeet/modal -S
```

```javascript
import Modal from '@eightfeet/modal';

const myModal = new Modal({
    style: {
        article: {
            borderRadius: '0.5em',
            backgroundColor: '#fff',
        }
	}
});

myModal.create({
    article: '这是一个弹窗'
}).then(() => console.log('弹窗已打开'));
```


#### parame

| 参数                      | 说明                         | 是否必填 | 备注                                                         | 类型     |
| ------------------------- | ---------------------------- | -------- | ------------------------------------------------------------ | -------- |
| id                        | 所创建弹窗的id               | 否       | 不传可自动生成id（modal + 时间戳 + 100以内的随机数）         | String   |
| zIndex                    | modal的样式层级关系          | 否       | 默认100                                                      | Number   |
| emBase                    | em单位的基准像素             | 否       | 默认自动计算（emBase = document.clientWidth/24）             | Number   |
| parentId                  | 所挂载的父级ID用于做局部弹窗 | 否       | 默认挂在body下面，指定父级dom时将挂载在父级dom下，配合css实现局部弹窗 | String   |
| closable                  | 是否可关闭                   | 否       | 默认true                                                     | Boolean  |
| shouldCloseOnOverlayClick | 是否点击蒙层关闭弹窗         | 否       | 默认false                                                    | Boolean  |
| style                     | 弹窗样式                     | 是       | 定义modal样式<br /> {<br />    overlay: 覆盖层, <br />    wrap: 模块包裹层, <br />    content: 内容区, <br />    header: 头部, <br />    article: 内容区, <br />    close: 关闭按钮, <br />    modify: 修饰器<br />}, <br />modify修饰器 是一个数组，每个数组元素对应会创建一个 基于弹窗的绝对定位div层，用于修饰弹窗（参考case） | Object   |
| animation                 | 弹窗动画                     | 否       | {<br />    form: 弹窗动画形式，参考animation附表,<br />    duration：持续时长<br />} | Object   |
| onCancel                  | 关闭弹窗                     |          | 关闭弹窗时的回调                                             | Function |

###### animation附表

| 参数        | 说明               | 备注 |
| ----------- | ------------------ | ---- |
| fadeInUp    | 从底部向上淡入     |      |
| fadeInDown  | 从顶部向下淡入     |      |
| fadeInLeft  | 从左向右淡入       |      |
| fadeInRight | 从右向左淡入       |      |
| zoomIn      | 从中心放大淡入     | 默认 |
| zoomInUp    | 从底部向上放大淡入 |      |
| zoomInDown  | 从顶部向下放大淡入 |      |
| zoomInLeft  | 从左向右放大淡入   |      |
| zoomInRight | 从右向左放大淡入   |      |



#### options

1. ##### create: ƒ (elements, doNotRemove) 创建弹窗
   ```typescript
   /**
     * @description 创建弹窗
     * @param {{
     *         header: InnerHTML;
     *         article: InnerHTML;
     *         footer: InnerHTML;
     *     }} elements 弹窗元素
     * @param {boolean} doNotRemove 是否移除弹窗
     * @memberof Modal
     */
   ```

2. ##### hide: ƒ (doNotRemove) 隐藏弹窗

   ```typescript
   /**
     * @description 移除弹窗
     * @memberof Modal
     */
   ```

3. ##### remove: ƒ () 移除弹窗

   移除，将弹窗从body中移除。

4. ##### show: ƒ () 显示弹窗

   显示页面弹窗，如果创建的弹窗隐藏时，调用此方法显示弹窗。

### createInlineStyles

    createInlineStyles: 创建行内样式、 

```javascript
    import {createInlineStyles} from '@eightfeet/modal';
``` 
    
### saferInnerHtml  
    InnerHtml 具有一定安全隐患，saferInnerHtml用于过滤模版中的危险脚本，让你安全使用InnerHtml
    避免XSS 攻击，默认InnerHtml都有通过saferInnerHtml转译为安全html

```javascript
    import {saferInnerHtml} from '@eightfeet/modal';
    const htmlStr = saferInnerHtml('<img src="x" onerror="alert(1)" />')
    console.log(htmlStr); // <img src="x" />
```

#### case

```javascript
import Modal from '@eightfeet/modal';

const newModal = new Modal({
        id: 'modalId', // 所创建弹窗的id 不传可自动生成id（modal + 时间戳 + 100以内的随机数）
        zIndex: 100, // modal的层级关系，默认100
        emBase: 12, // 基准像素 parent Dom’s fontsize
        animation: {
           from: 'bottom',
           duration: '2s'
        }, // 启用动画 默认true
        parentId: 'indom', // modal的创建位置，默认创建在body下
        closable: false, // modal是否可关闭 默认true
        shouldCloseOnOverlayClick: true, // 点击背景层关闭弹窗 默认false
        style: { // 定义modal样式 {overlay: 覆盖层, content: 内容区, close: 关闭按钮} 
            overlay: {
                backgroundColor: 'rgba(0,0,0,0.5)'
            },
            content: {
                backgroundColor: 'rgba(100, 100, 100, 0.2)',
                width: '19em',
                // padding: '120px',
                // 设置内容的层级关系
                zIndex: 107
            },
            close: {
                backgroundColor: 'rgba(0, 0, 0, 1)',
                width: '1em',
                height: '1em',
                top: '-3em',
                left: '50%'
            },
            // modify(修饰层)层级按照zIndex（modal的层级）以2为步值递增
            modify: [
                {
                    backgroundColor: 'rgba(0, 0, 255, 0.4)',
                    width: '120%',
                    left: '-10%',
                    height: '200px',
                    border: '1px solid rgba(0, 0, 255, 0.6)',
                    top: '-5em'
                },
                {
                    backgroundColor: 'rgba(0, 0, 255, 0.4)',
                    width: '130%',
                    left: '-15%',
                    height: '200px',
                    border: '1px solid rgba(0, 0, 255, 0.6)',
                    top: '-4em'
                }
            ]
        }
    });

    const btn = document.getElementById('exampleBtn');

    btn.onclick = function(){ 
        return newModal.create({
            header:'<div style="position:relative; z-index: 90;background-color: yellow;">头部</div>',
            article: `<div style="background-color: #fff;">
                        这是一段内容
                        <input id="inp" type="text" />
                    </div>`,
            footer: `<div style="background-color: white">
                        <button id="close" style="border:1px solid #aaa; padding: 1em">确定</button>
                        <br>
                        脚部
                    </div>`
        }, true).then(function(){
            document.getElementById('close').onclick = function(){
                console.log(document.getElementById('inp').value);
                return newModal.hide(true);
            };
        });
    }
    
```

## react 
### Modal组件最佳实践 
[demo](./ReactModal.tsx)
```typescript
    <Modal 
        visible={visible}
        onCancel={() => setVisible(false)}
        overlayStyle={{background: 'rgba(0, 255, 0, 0.5)'}}
    >
        <div>这是一个弹窗</div>
        <button onClick={() => setVisible(false)}>关闭弹窗</button>
    </Modal>
```

### react hook
- ### case react useModal hook

```typescript
    import { useRef, useCallback, useMemo, useEffect } from "react";
    import Modal, { ModalParameters } from "@eightfeet/modal";

    const useModal = (parameters: ModalParameters) => {
    const ref = useRef<Modal>();
    useMemo(() => {
        ref.current = new Modal(parameters);
    }, [parameters]);

    useEffect(() => {
        return () => {
        if (ref.current) {
            const previousModal = ref.current;
            if (document.getElementById(previousModal.state.id as string)) {
            previousModal.remove();
            }
        }
        }
    }, [])

    const createModal = useCallback<Modal['create']>((data) => {
        return ref.current?.create(data) || Promise.reject('modal is not ready yet!');
    }, []);

    const hideModal = useCallback<Modal["hide"]>((doNotRemove) => {
        return ref.current?.hide(doNotRemove) || Promise.reject('modal is not ready yet!');
    }, []);

    return { createModal, hideModal, modal: ref.current }
    };

    export default useModal;




```

- ### useModal 

```typescript

    import React from "react";
    import useModal from "./hooks/useModal";

    function App() {
        const { createModal, hideModal } = useModal({
            style: {
                content: {
                    width: '301px'
                }
            }
        });

        return (
            <div className="App">
            <button
                onClick={() =>
                createModal({ article: "<div>messages!</div>" }).then(() =>
                    setTimeout(hideModal, 1000)
                )
                }
            >
                弹窗
            </button>
            </div>
        );
    }

    export default App;
```

---
_Source: https://npm.io/package/@eightfeet/modal · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
