UNPKG

uikit

Version:

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

160 lines (112 loc) 4.14 kB
import Margin from './margin'; import Class from '../mixin/class'; import {addClass, children, css, height as getHeight, hasClass, scrolledOver, sortBy, toFloat, toggleClass} from 'uikit-util'; export default { extends: Margin, mixins: [Class], name: 'grid', props: { masonry: Boolean, parallax: Number }, data: { margin: 'uk-grid-margin', clsStack: 'uk-grid-stack', masonry: false, parallax: 0 }, connected() { this.masonry && addClass(this.$el, 'uk-flex-top uk-flex-wrap-top'); }, update: [ { write({columns}) { toggleClass(this.$el, this.clsStack, columns.length < 2); }, events: ['resize'] }, { read(data) { let {columns, rows} = data; // Filter component makes elements positioned absolute if (!columns.length || !this.masonry && !this.parallax || positionedAbsolute(this.$el)) { data.translates = false; return false; } let translates = false; const nodes = children(this.$el); const columnHeights = getColumnHeights(columns); const margin = getMarginTop(nodes, this.margin) * (rows.length - 1); const elHeight = Math.max(...columnHeights) + margin; if (this.masonry) { columns = columns.map(column => sortBy(column, 'offsetTop')); translates = getTranslates(rows, columns); } let padding = Math.abs(this.parallax); if (padding) { padding = columnHeights.reduce((newPadding, hgt, i) => Math.max(newPadding, hgt + margin + (i % 2 ? padding : padding / 8) - elHeight) , 0); } return {padding, columns, translates, height: translates ? elHeight : ''}; }, write({height, padding}) { css(this.$el, 'paddingBottom', padding || ''); height !== false && css(this.$el, 'height', height); }, events: ['resize'] }, { read({height}) { if (positionedAbsolute(this.$el)) { return false; } return { scrolled: this.parallax ? scrolledOver(this.$el, height ? height - getHeight(this.$el) : 0) * Math.abs(this.parallax) : false }; }, write({columns, scrolled, translates}) { if (scrolled === false && !translates) { return; } columns.forEach((column, i) => column.forEach((el, j) => css(el, 'transform', !scrolled && !translates ? '' : `translateY(${ (translates && -translates[i][j]) + (scrolled ? i % 2 ? scrolled : scrolled / 8 : 0) }px)`) ) ); }, events: ['scroll', 'resize'] } ] }; function positionedAbsolute(el) { return children(el).some(el => css(el, 'position') === 'absolute'); } function getTranslates(rows, columns) { const rowHeights = rows.map(row => Math.max(...row.map(el => el.offsetHeight)) ); return columns.map(elements => { let prev = 0; return elements.map((element, row) => prev += row ? rowHeights[row - 1] - elements[row - 1].offsetHeight : 0 ); }); } function getMarginTop(nodes, cls) { const [node] = nodes.filter(el => hasClass(el, cls)); return toFloat(node ? css(node, 'marginTop') : css(nodes[0], 'paddingLeft')); } function getColumnHeights(columns) { return columns.map(column => column.reduce((sum, el) => sum + el.offsetHeight, 0) ); }