UNPKG

uikit

Version:

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

104 lines (71 loc) 2.54 kB
import {$, $$, addClass, closest, escape, filter, height, isInView, offset, removeClass, trigger} from 'uikit-util'; export default { 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(_, $el) { return $$('a[href^="#"]', $el).filter(el => el.hash); }, elements({closest: selector}) { return closest(this.links, selector || '*'); }, targets() { return $$(this.links.map(el => escape(el.hash).substr(1)).join(',')); } }, update: [ { read() { if (this.scroll) { this.$create('scroll', this.links, {offset: this.offset || 0}); } } }, { read(data) { const scroll = window.pageYOffset + this.offset + 1; const max = height(document) - height(window) + this.offset; data.active = false; this.targets.every((el, i) => { const {top} = offset(el); const last = i + 1 === this.targets.length; if (!this.overflow && (i === 0 && top > scroll || last && top + el.offsetTop < scroll)) { return false; } if (!last && offset(this.targets[i + 1]).top <= scroll) { return true; } if (scroll >= max) { for (let j = this.targets.length - 1; j > i; j--) { if (isInView(this.targets[j])) { el = this.targets[j]; break; } } } return !(data.active = $(filter(this.links, `[href="#${el.id}"]`))); }); }, write({active}) { this.links.forEach(el => el.blur()); removeClass(this.elements, this.cls); if (active) { trigger(this.$el, 'active', [active, addClass(this.closest ? closest(active, this.closest) : active, this.cls)]); } }, events: ['scroll', 'resize'] } ] };