vue3-chat-scroll-next
Version:
Automatic, yet conditional, scroll-to-bottom directive for Vue.js 3.0
94 lines (81 loc) • 2.94 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global['vue-chat-scroll'] = factory());
}(this, (function () { 'use strict';
/**
* @name VueJS vChatScroll (vue-chat-scroll)
* @description Monitors an element and scrolls to the bottom if a new child is added
* @author Theodore Messinezis <theo@theomessin.com>
* @file v-chat-scroll directive definition
*/
var scrollToBottom = function scrollToBottom(el, smooth) {
if (typeof el.scroll === "function") {
el.scroll({
top: el.scrollHeight,
behavior: smooth ? 'smooth' : 'instant'
});
} else {
el.scrollTop = el.scrollHeight;
}
};
var mount = function mount(el, binding) {
var scrolled = false;
el.addEventListener('scroll', function (e) {
scrolled = el.scrollTop + el.clientHeight + 1 < el.scrollHeight;
if (scrolled && el.scrollTop === 0) {
el.dispatchEvent(new Event("v-chat-scroll-top-reached"));
}
});
new MutationObserver(function (e) {
var config = binding.value || {};
if (config.enabled === false) return;
var pause = config.always === false && scrolled;
var addedNodes = e[e.length - 1].addedNodes.length;
var removedNodes = e[e.length - 1].removedNodes.length;
if (config.scrollonremoved) {
if (pause || addedNodes != 1 && removedNodes != 1) return;
} else {
if (pause || addedNodes != 1) return;
}
var smooth = config.smooth;
var loadingRemoved = !addedNodes && removedNodes === 1;
if (loadingRemoved && config.scrollonremoved && 'smoothonremoved' in config) {
smooth = config.smoothonremoved;
}
scrollToBottom(el, smooth);
}).observe(el, {
childList: true,
subtree: true
});
};
var vChatScroll = {
mounted: function mounted(el, binding) {
mount(el, binding);
},
// For backwards compat with Vue 2.x
bind: function bind(el, binding) {
mount(el, binding);
},
// For backwards compat with Vue 2.x
inserted: function inserted(el, binding) {
var config = binding.value || {};
scrollToBottom(el, config.notSmoothOnInit ? false : config.smooth);
}
};
/**
* @name VueJS vChatScroll (vue-chat-scroll)
* @description Monitors an element and scrolls to the bottom if a new child is added
* @author Theodore Messinezis <theo@theomessin.com>
* @file vue-chat-scroll plugin definition
*/
var VueChatScroll = {
install: function install(Vue, options) {
Vue.directive('chat-scroll', vChatScroll);
}
};
if (typeof window !== 'undefined' && window.Vue && window.Vue.use) {
window.Vue.use(VueChatScroll);
}
return VueChatScroll;
})));