diff --git a/dist/index.js b/dist/index.js index bcbf5ec..300d4df 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1,55 +1,95 @@ -'use strict'; +"use strict"; Object.defineProperty(exports, "__esModule", { - value: true + value: true, }); exports.useModali = undefined; -var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); +var _slicedToArray = (function () { + function sliceIterator(arr, i) { + var _arr = []; + var _n = true; + var _d = false; + var _e = undefined; + try { + for ( + var _i = arr[Symbol.iterator](), _s; + !(_n = (_s = _i.next()).done); + _n = true + ) { + _arr.push(_s.value); + if (i && _arr.length === i) break; + } + } catch (err) { + _d = true; + _e = err; + } finally { + try { + if (!_n && _i["return"]) _i["return"](); + } finally { + if (_d) throw _e; + } + } + return _arr; + } + return function (arr, i) { + if (Array.isArray(arr)) { + return arr; + } else if (Symbol.iterator in Object(arr)) { + return sliceIterator(arr, i); + } else { + throw new TypeError( + "Invalid attempt to destructure non-iterable instance" + ); + } + }; +})(); -var _react = require('react'); +var _react = require("react"); var _react2 = _interopRequireDefault(_react); -var _reactDom = require('react-dom'); +var _reactDom = require("react-dom"); var _reactDom2 = _interopRequireDefault(_reactDom); -var _propTypes = require('prop-types'); +var _propTypes = require("prop-types"); var _propTypes2 = _interopRequireDefault(_propTypes); -var _classnames = require('classnames'); +var _classnames = require("classnames"); var _classnames2 = _interopRequireDefault(_classnames); -var _shortid = require('shortid'); +var _shortid = require("shortid"); var _shortid2 = _interopRequireDefault(_shortid); -require('./modali.css'); +require("../src/modali.css"); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { default: obj }; +} var Button = function Button(_ref) { var onClick = _ref.onClick, - label = _ref.label, - isStyleDefault = _ref.isStyleDefault, - isStyleCancel = _ref.isStyleCancel, - isStyleDestructive = _ref.isStyleDestructive; + label = _ref.label, + isStyleDefault = _ref.isStyleDefault, + isStyleCancel = _ref.isStyleCancel, + isStyleDestructive = _ref.isStyleDestructive; var buttonClass = (0, _classnames2.default)({ - 'modali-button': true, - 'modali-button-cancel': isStyleCancel, - 'modali-button-default': isStyleDefault, - 'modali-button-destructive': isStyleDestructive + "modali-button": true, + "modali-button-cancel": isStyleCancel, + "modali-button-default": isStyleDefault, + "modali-button-destructive": isStyleDestructive, }); return _react2.default.createElement( - 'button', + "button", { - type: 'button', + type: "button", className: buttonClass, - onClick: onClick + onClick: onClick, }, label ); @@ -58,7 +98,7 @@ var Button = function Button(_ref) { Button.defaultProps = { isStyleDefault: false, isStyleCancel: false, - isStyleDestructive: false + isStyleDestructive: false, }; Button.propTypes = { @@ -66,17 +106,17 @@ Button.propTypes = { label: _propTypes2.default.string.isRequired, isStyleDefault: _propTypes2.default.bool, isStyleCancel: _propTypes2.default.bool, - isStyleDestructive: _propTypes2.default.bool + isStyleDestructive: _propTypes2.default.bool, }; var Modal = function Modal(_ref2) { var isModalVisible = _ref2.isModalVisible, - hide = _ref2.hide, - options = _ref2.options, - children = _ref2.children; + hide = _ref2.hide, + options = _ref2.options, + children = _ref2.children; function handleOverlayClicked(e) { - if (e.target.className !== 'modali-wrapper') { + if (e.target.className !== "modali-wrapper") { return; } if (options === undefined) { @@ -94,10 +134,11 @@ var Modal = function Modal(_ref2) { function renderBody() { if (children) { return children; - }if (options && options.message) { + } + if (options && options.message) { return _react2.default.createElement( - 'div', - { className: 'modali-body-style' }, + "div", + { className: "modali-body-style" }, options.message ); } @@ -108,13 +149,13 @@ var Modal = function Modal(_ref2) { var buttons = options.buttons; return _react2.default.createElement( - 'div', - { className: 'modali-footer' }, + "div", + { className: "modali-footer" }, buttons.map(function (button) { return _react2.default.createElement( _react2.default.Fragment, { - key: _shortid2.default.generate() + key: _shortid2.default.generate(), }, button ); @@ -123,86 +164,116 @@ var Modal = function Modal(_ref2) { } var modaliWrapperClass = (0, _classnames2.default)({ - 'modali-wrapper': true, - 'modali-wrapper-centered': options && options.centered + "modali-wrapper": true, + "modali-wrapper-centered": options && options.centered, }); var modaliClass = (0, _classnames2.default)({ modali: true, - 'modali-size-large': options && options.large, - 'modali-size-regular': !options || options && !options.large, - 'modali-animated modali-animation-fade-in': options && options.animated + "modali-size-large": options && options.large, + "modali-size-regular": !options || (options && !options.large), + "modali-animated modali-animation-fade-in": options && options.animated, }); - return isModalVisible ? _reactDom2.default.createPortal(_react2.default.createElement( - _react2.default.Fragment, - null, - _react2.default.createElement('div', { className: 'modali-overlay' }), - _react2.default.createElement( - 'div', - { className: modaliWrapperClass, 'aria-modal': true, 'aria-hidden': true, tabIndex: -1, role: 'dialog', onClick: handleOverlayClicked }, - _react2.default.createElement( - 'div', - { className: modaliClass }, + return isModalVisible + ? _reactDom2.default.createPortal( _react2.default.createElement( - 'div', - { className: 'modali-content' }, - options !== undefined && options.closeButton === false ? null : _react2.default.createElement( - 'div', - { className: 'modali-header' }, - options !== undefined && options.title !== undefined && _react2.default.createElement( - 'div', - { className: 'modali-title' }, - options.title - ), + _react2.default.Fragment, + null, + _react2.default.createElement("div", { className: "modali-overlay" }), + _react2.default.createElement( + "div", + { + className: modaliWrapperClass, + "aria-modal": true, + "aria-hidden": true, + tabIndex: -1, + role: "dialog", + onClick: handleOverlayClicked, + }, _react2.default.createElement( - 'button', - { type: 'button', className: 'modali-close-button', 'data-dismiss': 'modal', 'aria-label': 'Close', onClick: hide }, + "div", + { className: modaliClass }, _react2.default.createElement( - 'span', - { 'aria-hidden': 'true' }, - '\xD7' + "div", + { className: "modali-content" }, + options !== undefined && options.closeButton === false + ? null + : _react2.default.createElement( + "div", + { className: "modali-header" }, + options !== undefined && + options.title !== undefined && + _react2.default.createElement( + "div", + { className: "modali-title" }, + options.title + ), + _react2.default.createElement( + "button", + { + type: "button", + className: "modali-close-button", + "data-dismiss": "modal", + "aria-label": "Close", + onClick: hide, + }, + _react2.default.createElement( + "span", + { "aria-hidden": "true" }, + "\xD7" + ) + ) + ), + _react2.default.createElement( + "div", + { className: "modali-body" }, + renderBody() + ), + options && + options.buttons && + options.buttons.length > 0 && + renderFooter() ) ) - ), - _react2.default.createElement( - 'div', - { className: 'modali-body' }, - renderBody() - ), - options && options.buttons && options.buttons.length > 0 && renderFooter() - ) + ) + ), + document.body ) - ) - ), document.body) : null; + : null; }; var Modali = function Modali() {}; Modali.Button = Button; Modali.Modal = Modal; exports.default = Modali; -var useModali = exports.useModali = function useModali(options) { +var useModali = (exports.useModali = function useModali(options) { var _useState = (0, _react.useState)(false), - _useState2 = _slicedToArray(_useState, 2), - hasToggledBefore = _useState2[0], - setHasToggledBefore = _useState2[1]; + _useState2 = _slicedToArray(_useState, 2), + hasToggledBefore = _useState2[0], + setHasToggledBefore = _useState2[1]; var _useState3 = (0, _react.useState)(false), - _useState4 = _slicedToArray(_useState3, 2), - isModalVisible = _useState4[0], - setIsModalVisible = _useState4[1]; + _useState4 = _slicedToArray(_useState3, 2), + isModalVisible = _useState4[0], + setIsModalVisible = _useState4[1]; var _useState5 = (0, _react.useState)(false), - _useState6 = _slicedToArray(_useState5, 2), - isShown = _useState6[0], - setIsShown = _useState6[1]; + _useState6 = _slicedToArray(_useState5, 2), + isShown = _useState6[0], + setIsShown = _useState6[1]; var isModalVisibleRef = (0, _react.useRef)(isModalVisible); isModalVisibleRef.current = isModalVisible; var timeoutHack = void 0; - function toggle() { - timeoutHack = setTimeout(function () { + function handleDismiss() { + const dismiss = document.querySelector(".modali-animation-fade-in"); + dismiss.classList.add("modali-animation-fade-out"); + } + + function showOrHide() { + timeoutHack = setTimeout(() => { setIsModalVisible(!isModalVisibleRef.current); clearTimeout(timeoutHack); }, 10); @@ -210,37 +281,55 @@ var useModali = exports.useModali = function useModali(options) { setHasToggledBefore(true); } + function toggle() { + if (!isShown === false && options.animated) { + handleDismiss(); + setTimeout(() => { + showOrHide(); + }, 300); + } else { + showOrHide(); + } + } + function handleKeyDown(event) { - if (event.keyCode !== 27 || options && options.keyboardClose === false) return; + if (event.keyCode !== 27 || (options && options.keyboardClose === false)) + return; toggle(); if (options && options.onEscapeKeyDown) { options.onEscapeKeyDown(); } } - (0, _react.useEffect)(function () { - if (isShown) { - if (options && options.onShow) { - options.onShow(); + (0, _react.useEffect)( + function () { + if (isShown) { + if (options && options.onShow) { + options.onShow(); + } + document.addEventListener("keydown", handleKeyDown); + document.body.classList.add("modali-open"); } - document.addEventListener('keydown', handleKeyDown); - document.body.classList.add('modali-open'); - } - if (!isShown && hasToggledBefore) { - if (options && options.onHide) { - options.onHide(); + if (!isShown && hasToggledBefore) { + if (options && options.onHide) { + options.onHide(); + } + document.body.classList.remove("modali-open"); } - document.body.classList.remove('modali-open'); - } - return function () { - return document.removeEventListener('keydown', handleKeyDown); - }; - }, [isShown]); - - return [{ - isShown: isShown, - isModalVisible: isModalVisible, - hide: toggle, - options: options - }, toggle]; -}; \ No newline at end of file + return function () { + return document.removeEventListener("keydown", handleKeyDown); + }; + }, + [isShown] + ); + + return [ + { + isShown: isShown, + isModalVisible: isModalVisible, + hide: toggle, + options: options, + }, + toggle, + ]; +}); diff --git a/src/index.js b/src/index.js index 6dba248..fc59067 100644 --- a/src/index.js +++ b/src/index.js @@ -1,25 +1,25 @@ -import React, { useState, useEffect, useRef } from 'react'; -import ReactDOM from 'react-dom'; -import PropTypes from 'prop-types'; -import classNames from 'classnames'; -import shortid from 'shortid'; -import './modali.css'; +import classNames from "classnames"; +import PropTypes from "prop-types"; +import React, { useEffect, useRef, useState } from "react"; +import ReactDOM from "react-dom"; +import shortid from "shortid"; +import "./modali.css"; const Button = ({ - onClick, label, isStyleDefault, isStyleCancel, isStyleDestructive, + onClick, + label, + isStyleDefault, + isStyleCancel, + isStyleDestructive, }) => { const buttonClass = classNames({ - 'modali-button': true, - 'modali-button-cancel': isStyleCancel, - 'modali-button-default': isStyleDefault, - 'modali-button-destructive': isStyleDestructive, + "modali-button": true, + "modali-button-cancel": isStyleCancel, + "modali-button-default": isStyleDefault, + "modali-button-destructive": isStyleDestructive, }); return ( - ); @@ -39,11 +39,9 @@ Button.propTypes = { isStyleDestructive: PropTypes.bool, }; -const Modal = ({ - isModalVisible, hide, options, children, -}) => { +const Modal = ({ isModalVisible, hide, options, children }) => { function handleOverlayClicked(e) { - if (e.target.className !== 'modali-wrapper') { + if (e.target.className !== "modali-wrapper") { return; } if (options === undefined) { @@ -61,12 +59,9 @@ const Modal = ({ function renderBody() { if (children) { return children; - } if (options && options.message) { - return ( -
- {options.message} -
- ); + } + if (options && options.message) { + return
{options.message}
; } return false; } @@ -75,56 +70,68 @@ const Modal = ({ const { buttons } = options; return (
- {buttons.map(button => ( - - {button} - + {buttons.map((button) => ( + {button} ))}
); } const modaliWrapperClass = classNames({ - 'modali-wrapper': true, - 'modali-wrapper-centered': options && options.centered, + "modali-wrapper": true, + "modali-wrapper-centered": options && options.centered, }); const modaliClass = classNames({ modali: true, - 'modali-size-large': options && options.large, - 'modali-size-regular': !options || (options && !options.large), - 'modali-animated modali-animation-fade-in': options && options.animated, + "modali-size-large": options && options.large, + "modali-size-regular": !options || (options && !options.large), + "modali-animated modali-animation-fade-in": options && options.animated, }); - return isModalVisible ? ReactDOM.createPortal( - -
-
-
-
- {options !== undefined && options.closeButton === false ? null : ( -
- {options !== undefined && options.title !== undefined && ( -
- {options.title} + return isModalVisible + ? ReactDOM.createPortal( + +
+
+
+
+ {options !== undefined && + options.closeButton === false ? null : ( +
+ {options !== undefined && options.title !== undefined && ( +
{options.title}
+ )} +
)} - +
{renderBody()}
+ {options && + options.buttons && + options.buttons.length > 0 && + renderFooter()}
- )} -
- {renderBody()}
- {options && options.buttons && options.buttons.length > 0 && renderFooter()}
-
-
-
, document.body, - ) : null; + , + document.body + ) + : null; }; const Modali = () => {}; @@ -140,7 +147,12 @@ export const useModali = (options) => { isModalVisibleRef.current = isModalVisible; let timeoutHack; - function toggle() { + function handleDismiss() { + const dismiss = document.querySelector(".modali-animation-fade-in"); + dismiss.classList.add("modali-animation-fade-out"); + } + + function showOrHide() { timeoutHack = setTimeout(() => { setIsModalVisible(!isModalVisibleRef.current); clearTimeout(timeoutHack); @@ -149,8 +161,20 @@ export const useModali = (options) => { setHasToggledBefore(true); } + function toggle() { + if (!isShown === false && options.animated) { + handleDismiss(); + setTimeout(() => { + showOrHide(); + }, 300); + } else { + showOrHide(); + } + } + function handleKeyDown(event) { - if (event.keyCode !== 27 || (options && options.keyboardClose === false)) return; + if (event.keyCode !== 27 || (options && options.keyboardClose === false)) + return; toggle(); if (options && options.onEscapeKeyDown) { options.onEscapeKeyDown(); @@ -162,16 +186,16 @@ export const useModali = (options) => { if (options && options.onShow) { options.onShow(); } - document.addEventListener('keydown', handleKeyDown); - document.body.classList.add('modali-open'); + document.addEventListener("keydown", handleKeyDown); + document.body.classList.add("modali-open"); } if (!isShown && hasToggledBefore) { if (options && options.onHide) { options.onHide(); } - document.body.classList.remove('modali-open'); + document.body.classList.remove("modali-open"); } - return () => document.removeEventListener('keydown', handleKeyDown); + return () => document.removeEventListener("keydown", handleKeyDown); }, [isShown]); return [ diff --git a/src/modali.css b/src/modali.css index 6225c70..9d139eb 100644 --- a/src/modali.css +++ b/src/modali.css @@ -6,13 +6,13 @@ width: 100vw; height: 100vh; background-color: #000; - opacity: .5; + opacity: 0.5; } .modali-wrapper { display: inline-table; position: fixed; - padding: .5rem; + padding: 0.5rem; top: 0; left: 0; z-index: 1050; @@ -39,7 +39,7 @@ .modali-header { display: flex; align-items: flex-start; - padding: 1.5rem 1.5rem .5rem 1.5rem; + padding: 1.5rem 1.5rem 0.5rem 1.5rem; } .modali-header .modali-title { @@ -55,14 +55,14 @@ font-weight: 700; line-height: 1; color: #000; - opacity: .3; + opacity: 0.3; cursor: pointer; border: none; outline: 0 !important; } .modali-close-button:hover { - opacity: .8; + opacity: 0.8; text-decoration: none; } @@ -72,11 +72,11 @@ flex-direction: column; width: 100%; background-color: #fff; - border-radius: .3rem; + border-radius: 0.3rem; } .modali-body-style { - padding: .5rem 1.5rem; + padding: 0.5rem 1.5rem; } .modali-footer { @@ -136,12 +136,12 @@ /* Button Classes */ .modali-button { - font-size: .9rem; + font-size: 0.9rem; font-weight: 700; border: none; border-radius: 3px; - padding: .3rem 1rem; - margin-left: .5rem; + padding: 0.3rem 1rem; + margin-left: 0.5rem; } .modali-button-cancel { @@ -150,20 +150,20 @@ } .modali-button-destructive { - background: #FF1654; + background: #ff1654; color: #fff; } .modali-button-default { - background: #247BA0; + background: #247ba0; color: #fff; } /* Animation Classes */ .modali-animated { - -webkit-animation-duration: .5s; - animation-duration: .5s; + -webkit-animation-duration: 0.5s; + animation-duration: 0.5s; -webkit-animation-fill-mode: both; animation-fill-mode: both; } @@ -173,6 +173,11 @@ animation-name: fadeIn; } +.modali-animation-fade-out { + -webkit-animation-name: fadeOut; + animation-name: fadeOut; +} + @-webkit-keyframes fadeIn { from { opacity: 0; @@ -198,3 +203,29 @@ transform: translate3d(0, 0, 0); } } + +@-webkit-keyframes fadeOut { + from { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + to { + opacity: 0; + -webkit-transform: translate3d(0, 30%, 0); + transform: translate3d(0, 30%, 0); + } +} + +@keyframes fadeOut { + from { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + to { + opacity: 0; + -webkit-transform: translate3d(0, 30%, 0); + transform: translate3d(0, 30%, 0); + } +}