import { getOptions } from './config' import { getValueByPath} from './helpers' import { removeElement } from './helpers' export default { props: { /** Type (color) of the notification, optional. */ type: { type: String, }, /** Message text (can contain HTML). */ message: [String, Array], /** Visibility duration in miliseconds. */ duration: { type: Number, default: () => { return getValueByPath(getOptions(), 'notification.duration', 1000) } }, /** If should queue with others notices (snackbar/toast/notification). */ queue: { type: Boolean, default: () => { return getValueByPath(getOptions(), 'notification.noticeQueue', undefined) } }, /** Show the Notification indefinitely until it is dismissed when programmatically. */ indefinite: { type: Boolean, default: false }, /** Which position the notification will appear when programmatically. */ position: { type: String, default: 'top', validator(value) { return [ 'top-right', 'top', 'top-left', 'bottom-right', 'bottom', 'bottom-left' ].indexOf(value) > -1 } }, /** DOM element the toast will be created on. Note that this also changes the position of the toast from fixed to absolute. Meaning that the container should be fixed. */ container: { type: String, default: () => { return getValueByPath(getOptions(), 'notification.containerElement', undefined) } }, /** @ignore */ programmatic: Object, /** @ignore */ promise: Promise, /** Callback function to call after close (programmatically close or user canceled) */ onClose: { type: Function, default: () => {} } }, data() { return { isActive: false, parentTop: null, parentBottom: null, newDuration: this.duration, newContainer: this.container } }, computed: { correctParent() { switch (this.position) { case 'top-right': case 'top': case 'top-left': return this.parentTop case 'bottom-right': case 'bottom': case 'bottom-left': return this.parentBottom } }, transition() { switch (this.position) { case 'top-right': case 'top': case 'top-left': return { enter: 'fadeInDown', leave: 'fadeOut' } case 'bottom-right': case 'bottom': case 'bottom-left': return { enter: 'fadeInUp', leave: 'fadeOut' } } } }, methods: { shouldQueue() { if (!this.queue) return false return ( this.parentTop.childElementCount > 0 || this.parentBottom.childElementCount > 0 ) }, close() { clearTimeout(this.timer) this.$emit('close') this.onClose.apply(null, arguments) if (this.programmatic) { if (this.programmatic.instances) { this.programmatic.instances.remove(this) } if (this.programmatic.resolve) { this.programmatic.resolve.apply(null, arguments) } } // Timeout for the animation complete before destroying setTimeout(() => { this.isActive = false removeElement(this.$el) }, 150) }, showNotice() { if (this.shouldQueue()) this.correctParent.innerHTML = '' this.correctParent.insertAdjacentElement('afterbegin', this.$el) this.isActive = true if (!this.indefinite) { this.timer = setTimeout(() => this.timeoutCallback(), this.newDuration) } }, setupContainer() { this.parentTop = document.querySelector((this.newContainer ? this.newContainer : 'body') + `>.${this.rootClasses().join('.')}.${this.positionClasses('top').join('.')}`) this.parentBottom = document.querySelector((this.newContainer ? this.newContainer : 'body') + `>.${this.rootClasses().join('.')}.${this.positionClasses('bottom').join('.')}`) if (this.parentTop && this.parentBottom) return if (!this.parentTop) { this.parentTop = document.createElement('div') this.parentTop.className = `${this.rootClasses().join(' ')} ${this.positionClasses('top').join(' ')}` } if (!this.parentBottom) { this.parentBottom = document.createElement('div') this.parentBottom.className = `${this.rootClasses().join(' ')} ${this.positionClasses('bottom').join(' ')}` } const container = document.querySelector(this.newContainer) || document.body container.appendChild(this.parentTop) container.appendChild(this.parentBottom) if (this.newContainer) { this.parentTop.classList.add('has-custom-container') this.parentBottom.classList.add('has-custom-container') } }, timeoutCallback() { return this.close({action: 'close', method: 'timeout'}) } }, beforeMount() { this.setupContainer() }, mounted() { if (this.programmatic && this.programmatic.instances) { this.programmatic.instances.add(this) } this.showNotice() } }