UNPKG

jiro-ui

Version:

A Mithril.js UI library based from construct-ui

227 lines (226 loc) 9.46 kB
import { __assign, __extends } from "tslib"; import classnames from 'classnames'; import m from 'mithril'; import { Classes, safeCall, Keys, getScrollbarWidth, hasScrollbar } from '../../_shared'; import { AbstractComponent } from '../abstract-component'; import { Portal } from '../portal'; import { TransitionManager } from '../../utils'; var instanceCounter = 0; var Overlay = /** @class */ (function (_super) { __extends(Overlay, _super); function Overlay() { var _this = _super !== null && _super.apply(this, arguments) || this; _this.id = instanceCounter++; _this.shouldRender = false; _this.onContainerCreate = function (_a) { var dom = _a.dom; if (_this.shouldRender) { _this.handleOpen(dom); } }; _this.onContainerUpdate = function (_a) { var dom = _a.dom; var isOpen = _this.attrs.isOpen; var wasOpen = _this.prevAttrs.isOpen; if (isOpen && !wasOpen) { _this.handleOpen(dom); } else if (!isOpen && wasOpen) { _this.handleClose(); } }; _this.handleBackdropMouseDown = function (e) { var _a = _this.attrs, closeOnOutsideClick = _a.closeOnOutsideClick, onClose = _a.onClose; if (closeOnOutsideClick) { safeCall(onClose, e); } else e.redraw = false; }; _this.handleDocumentMouseDown = function (e) { var _a = _this.attrs, isOpen = _a.isOpen, onClose = _a.onClose, closeOnOutsideClick = _a.closeOnOutsideClick; var contentEl = _this.contentEl; var isClickOnOverlay = contentEl && contentEl.contains(e.target); if (isOpen && closeOnOutsideClick && !isClickOnOverlay && _this.lastOpened) { safeCall(onClose, e); m.redraw(); } }; _this.handleKeyDown = function (e) { var _a = _this.attrs, closeOnEscapeKey = _a.closeOnEscapeKey, onClose = _a.onClose; if (e.which === Keys.ESCAPE && closeOnEscapeKey && _this.lastOpened) { safeCall(onClose, e); e.preventDefault(); m.redraw(); } }; return _this; } Overlay.prototype.getDefaultAttrs = function () { return { closeOnEscapeKey: true, closeOnOutsideClick: true, hasBackdrop: true, addToStack: true, transitionName: 'fade', transitionDuration: TransitionManager.isEnabled ? 200 : 0 }; }; Overlay.prototype.oninit = function (vnode) { _super.prototype.oninit.call(this, vnode); this.shouldRender = !!vnode.attrs.isOpen; }; Overlay.prototype.onbeforeupdate = function (vnode, old) { var _this = this; _super.prototype.onbeforeupdate.call(this, vnode, old); var _a = vnode.attrs, isOpen = _a.isOpen, transitionDuration = _a.transitionDuration; var wasOpen = old.attrs.isOpen; if (isOpen && !wasOpen) { this.clearTimeouts(); this.shouldRender = true; } else if (!isOpen && wasOpen) { if (transitionDuration > 0) { this.handleClose(); this.setTimeout(function () { _this.shouldRender = false; m.redraw(); _this.handleClosed(); }, transitionDuration); } else { this.shouldRender = false; this.handleClose(); this.handleClosed(); } } }; Overlay.prototype.onremove = function () { if (this.shouldRender === true) { this.handleClose(); this.handleClosed(); this.shouldRender = false; } }; Overlay.prototype.view = function () { var _a = this.attrs, backdropClass = _a.backdropClass, hasBackdrop = _a.hasBackdrop, content = _a.content, inline = _a.inline, className = _a.class, style = _a.style, portalAttrs = _a.portalAttrs; if (!this.shouldRender) { return null; } var innerContent = [ hasBackdrop && m('', { class: classnames(Classes.OVERLAY_BACKDROP, backdropClass), onmousedown: this.handleBackdropMouseDown, tabindex: 0 }), content ]; var classes = classnames(Classes.OVERLAY, inline && Classes.OVERLAY_INLINE, className); var container = m('', { class: classes, style: style, oncreate: this.onContainerCreate, onupdate: this.onContainerUpdate }, innerContent); return inline ? container : m(Portal, __assign({}, portalAttrs), container); }; Overlay.prototype.handleOpen = function (contentEl) { var _a = this.attrs, addToStack = _a.addToStack, closeOnOutsideClick = _a.closeOnOutsideClick, closeOnEscapeKey = _a.closeOnEscapeKey, hasBackdrop = _a.hasBackdrop, onOpened = _a.onOpened, inline = _a.inline; this.contentEl = contentEl; if (addToStack) { Overlay.openStack.push(this.id); } if (closeOnOutsideClick && !hasBackdrop) { document.addEventListener('mousedown', this.handleDocumentMouseDown); } if (closeOnEscapeKey) { document.addEventListener('keydown', this.handleKeyDown); } this.handleEnterTransition(); if (hasBackdrop && !inline) { document.body.classList.add(Classes.OVERLAY_OPEN); var bodyHasScrollbar = hasScrollbar(document.body); if (bodyHasScrollbar) { document.body.style.paddingRight = getScrollbarWidth() + "px"; } } safeCall(onOpened, contentEl); this.handleFocus(); }; Overlay.prototype.handleClose = function () { document.removeEventListener('mousedown', this.handleDocumentMouseDown); document.removeEventListener('keydown', this.handleKeyDown); this.handleExitTransition(); }; Overlay.prototype.handleClosed = function () { var _this = this; var _a = this.attrs, restoreFocus = _a.restoreFocus, onClosed = _a.onClosed, hasBackdrop = _a.hasBackdrop, inline = _a.inline; if (this.attrs.addToStack) { Overlay.openStack = Overlay.openStack.filter(function (id) { return id !== _this.id; }); } if (this.lastActiveElement && restoreFocus) { window.requestAnimationFrame(function () { return _this.lastActiveElement.focus(); }); } if (hasBackdrop && !inline) { document.body.classList.remove(Classes.OVERLAY_OPEN); document.body.style.paddingRight = ''; } safeCall(onClosed); }; Overlay.prototype.handleEnterTransition = function () { var _a = this.attrs, transitionName = _a.transitionName, transitionDuration = _a.transitionDuration; var el = this.contentEl; if (el == null || transitionDuration === 0) return; el.classList.remove(transitionName + "-exit"); el.classList.remove(transitionName + "-exit-active"); el.classList.add(transitionName + "-enter"); // tslint:disable-next-line:no-unused-expression el.scrollTop; el.classList.add(transitionName + "-enter-active"); }; Overlay.prototype.handleExitTransition = function () { var _a = this.attrs, transitionDuration = _a.transitionDuration, transitionName = _a.transitionName; var el = this.contentEl; if (el == null || transitionDuration === 0) return; el.classList.remove(transitionName + "-enter"); el.classList.remove(transitionName + "-enter-active"); el.classList.add(transitionName + "-exit"); // tslint:disable-next-line:no-unused-expression el.scrollTop; el.classList.add(transitionName + "-exit-active"); }; Overlay.prototype.handleFocus = function () { this.lastActiveElement = document.activeElement; var contentEl = this.contentEl; var _a = this.attrs, isOpen = _a.isOpen, autofocus = _a.autofocus; if (!contentEl || !document.activeElement || !isOpen || !autofocus) { return; } window.requestAnimationFrame(function () { var isFocusOutsideOverlay = !contentEl.contains(document.activeElement); if (isFocusOutsideOverlay) { var autofocusEl = contentEl.querySelector('[autofocus]'); var tabIndexEl = contentEl.querySelector('[tabindex]'); if (autofocusEl) { autofocusEl.focus(); } else if (tabIndexEl) { tabIndexEl.focus(); } } }); }; Object.defineProperty(Overlay.prototype, "lastOpened", { get: function () { return this.attrs.addToStack ? Overlay.getLastOpened() === this.id : true; }, enumerable: false, configurable: true }); Overlay.openStack = []; Overlay.getLastOpened = function () { return Overlay.openStack[Overlay.openStack.length - 1]; }; return Overlay; }(AbstractComponent)); export { Overlay };