UNPKG

uikit

Version:

UIkit is a lightweight and modular front-end framework for developing fast and powerful web interfaces.

106 lines (87 loc) 2.76 kB
import Scroll from '../mixin/scroll'; import { $$, closest, hasClass, isVisible, offset, offsetViewport, scrollParents, toggleClass, trigger, } from 'uikit-util'; import { getTargetElement } from './scroll'; export default { mixins: [Scroll], props: { cls: String, closest: String, scroll: Boolean, overflow: Boolean, offset: Number, }, data: { cls: 'uk-active', closest: false, scroll: false, overflow: true, offset: 0, }, computed: { links: { get(_, $el) { return $$('a[href^="#"]', $el).filter((el) => el.hash); }, watch(links) { if (this.scroll) { this.$create('scroll', links, { offset: this.offset || 0 }); } }, immediate: true, }, elements({ closest: selector }) { return closest(this.links, selector || '*'); }, }, update: [ { read() { const targets = this.links.map(getTargetElement).filter(Boolean); const { length } = targets; if (!length || !isVisible(this.$el)) { return false; } const [scrollElement] = scrollParents(targets, /auto|scroll/, true); const { scrollTop, scrollHeight } = scrollElement; const viewport = offsetViewport(scrollElement); const max = scrollHeight - viewport.height; let active = false; if (scrollTop === max) { active = length - 1; } else { for (let i = 0; i < targets.length; i++) { if (offset(targets[i]).top - viewport.top - this.offset > 0) { break; } active = +i; } if (active === false && this.overflow) { active = 0; } } return { active }; }, write({ active }) { const changed = active !== false && !hasClass(this.elements[active], this.cls); this.links.forEach((el) => el.blur()); for (let i = 0; i < this.elements.length; i++) { toggleClass(this.elements[i], this.cls, +i === active); } if (changed) { trigger(this.$el, 'active', [active, this.elements[active]]); } }, events: ['scroll', 'resize'], }, ], };