UNPKG

jcore-ui

Version:

jcore-ui - components for building an interface

163 lines (127 loc) 4.19 kB
import Component, { IComponent, IComponentOn, IComponentOptions, IComponentSelector } from "../core/Component"; import config from '../../config'; import createElement from "../utils/createElement"; import event from "../utils/event"; import { $, JDom } from "../core/JDom"; const selectors = { element: `.${config.prefix}-modal`, overlay: `.${config.prefix}-modal-overlay`, content: `.${config.prefix}-modal-content`, close: `.${config.prefix}-modal-close`, btnTarget: `data-modal-target`, } interface IModalSelector extends IComponentSelector { overlay: string; content: string; close: string; btnTarget: string; } interface IModalOptions extends IComponentOptions { adaptive?: boolean; children?: HTMLElement[]; } interface IModalOn extends IComponentOn { // change?: (ctx?: Component) => void; } interface IModalElements { // $close?: HTMLElement $btnTarget?: JDom; $container?: JDom; } interface IModal extends IComponent { selectors?: IModalSelector; options?: IModalOptions; on?: IModalOn; elements?: IModalElements; } interface Modal { selectors: IModalSelector; $overlay: JDom; $close: JDom; $btnTarget: JDom; $container?: JDom; options: IModalOptions; on: IModalOn; props: IModal; isRender: boolean; } class Modal extends Component { constructor(props: IModal = {}) { super({ ...props, Component: Modal, selectors: Object.assign(selectors, props.selectors || {}) }); this.props = props; if (this.options && this.options.mount) { this.mount(); } } mount() { if (!this.$element || this._mount || this.$element.attr('data-mount')) { return; } super.mount(); this.options = Object.assign({ adaptive: this.$element.dataset.adaptive || true, }, this.options); this.handlers = { // change: this.change.bind(this) }; this.isRender = false; this.$overlay = $(`<div class="${this.selectors.overlay.replace('.', '')}"></div>`); this.$close = this.$element.find(this.selectors.close); this.$btnTarget = this.props.elements?.$btnTarget || $(`[${this.selectors.btnTarget}="${this.options.name}"]`); this.$container = $(this.props.elements?.$container || $(`body`)); this.addEvents(); this.on.mount(this); this.emitter.emit('mount', this); } addEvents() { if (this.options.adaptive) { this.$element.attr('data-adaptive', ''); } if (this.$btnTarget) { this.$btnTarget.on('click', e => this.render()); } this.$overlay.on('click', this.destroy.bind(this)); this.$close.on('click', this.destroy.bind(this)); } unmount() { super.unmount(); this.on.unmount(this); this.emitter.emit('unmount', this); } render() { $('body').style.setProperty('overflow', 'hidden'); this.$container.append(this.$overlay.get()); this.$container.append(this.$element.get()); this.isRender = true; this.on.render(this); this.emitter.emit('render', this); setTimeout(() => { this.$overlay.attr('data-active', ''); this.$element.attr('data-active', ''); }, 10); } destroy() { if (!this.isRender) { return; } this.$overlay.on(event.transitionEnd(), () => { this.$overlay.attr('data-closing', null); this.$element.attr('data-closing', null); this.$overlay.attr('data-active', null); this.$element.attr('data-active', null); this.$overlay.remove(); this.$element.remove(); }, { once: true }); this.$overlay.attr('data-closing', ''); this.$element.attr('data-closing', ''); this.isRender = false; this.on.destroy(this); this.emitter.emit('destroy', this); document.querySelector('body').style.removeProperty('overflow'); } } export default Modal