UNPKG

uikit

Version:

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

549 lines (430 loc) • 15 kB
/*! UIkit 3.14.1 | https://www.getuikit.com | (c) 2014 - 2022 YOOtheme | MIT License */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('uikit-util')) : typeof define === 'function' && define.amd ? define('uikitparallax', ['uikit-util'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.UIkitParallax = factory(global.UIkit.util)); })(this, (function (uikitUtil) { 'use strict'; var Resize = { connected() {var _this$$options$resize; this.registerObserver( uikitUtil.observeResize(((_this$$options$resize = this.$options.resizeTargets) == null ? void 0 : _this$$options$resize.call(this)) || this.$el, () => this.$emit('resize'))); } }; var Scroll = { connected() { registerScrollListener(this._uid, () => this.$emit('scroll')); }, disconnected() { unregisterScrollListener(this._uid); } }; const scrollListeners = new Map(); let unbindScrollListener; function registerScrollListener(id, listener) { unbindScrollListener = unbindScrollListener || uikitUtil.on(window, 'scroll', () => scrollListeners.forEach((listener) => listener()), { passive: true, capture: true }); scrollListeners.set(id, listener); } function unregisterScrollListener(id) { scrollListeners.delete(id); if (unbindScrollListener && !scrollListeners.size) { unbindScrollListener(); unbindScrollListener = null; } } var Media = { props: { media: Boolean }, data: { media: false }, connected() { const media = toMedia(this.media); this.matchMedia = true; if (media) { this.mediaObj = window.matchMedia(media); const handler = () => { this.matchMedia = this.mediaObj.matches; uikitUtil.trigger(this.$el, uikitUtil.createEvent('mediachange', false, true, [this.mediaObj])); }; this.offMediaObj = uikitUtil.on(this.mediaObj, 'change', () => { handler(); this.$emit('resize'); }); handler(); } }, disconnected() {var _this$offMediaObj; (_this$offMediaObj = this.offMediaObj) == null ? void 0 : _this$offMediaObj.call(this); } }; function toMedia(value) { if (uikitUtil.isString(value)) { if (uikitUtil.startsWith(value, '@')) { const name = "breakpoint-" + value.substr(1); value = uikitUtil.toFloat(uikitUtil.getCssVar(name)); } else if (isNaN(value)) { return value; } } return value && uikitUtil.isNumeric(value) ? "(min-width: " + value + "px)" : ''; } uikitUtil.memoize(async (src) => { if (src) { if (uikitUtil.startsWith(src, 'data:')) { return decodeURIComponent(src.split(',')[1]); } else { return (await fetch(src)).text(); } } else { return Promise.reject(); } }); function getMaxPathLength(el) { return Math.ceil( Math.max( 0, ...uikitUtil.$$('[stroke]', el).map((stroke) => { try { return stroke.getTotalLength(); } catch (e) { return 0; } }))); } const props = { x: transformFn, y: transformFn, rotate: transformFn, scale: transformFn, color: colorFn, backgroundColor: colorFn, borderColor: colorFn, blur: filterFn, hue: filterFn, fopacity: filterFn, grayscale: filterFn, invert: filterFn, saturate: filterFn, sepia: filterFn, opacity: cssPropFn, stroke: strokeFn, bgx: backgroundFn, bgy: backgroundFn }; const { keys } = Object; var Parallax = { mixins: [Media], props: fillObject(keys(props), 'list'), data: fillObject(keys(props), undefined), computed: { props(properties, $el) { return keys(props).reduce((result, prop) => { if (!uikitUtil.isUndefined(properties[prop])) { result[prop] = props[prop](prop, $el, properties[prop].slice()); } return result; }, {}); } }, events: { load() { this.$emit(); } }, methods: { reset() { for (const prop in this.getCss(0)) { uikitUtil.css(this.$el, prop, ''); } }, getCss(percent) { const css = { transform: '', filter: '' }; for (const prop in this.props) { this.props[prop](css, percent); } return css; } } }; function transformFn(prop, el, stops) { let unit = getUnit(stops) || { x: 'px', y: 'px', rotate: 'deg' }[prop] || ''; let transformFn; if (prop === 'x' || prop === 'y') { prop = "translate" + uikitUtil.ucfirst(prop); transformFn = (stop) => uikitUtil.toFloat(uikitUtil.toFloat(stop).toFixed(unit === 'px' ? 0 : 6)); } else if (prop === 'scale') { unit = ''; transformFn = (stop) => getUnit([stop]) ? uikitUtil.toPx(stop, 'width', el, true) / el.offsetWidth : stop; } if (stops.length === 1) { stops.unshift(prop === 'scale' ? 1 : 0); } stops = parseStops(stops, transformFn); return (css, percent) => { css.transform += " " + prop + "(" + getValue(stops, percent) + unit + ")"; }; } function colorFn(prop, el, stops) { if (stops.length === 1) { stops.unshift(getCssValue(el, prop, '')); } stops = parseStops(stops, (stop) => parseColor(el, stop)); return (css, percent) => { const [start, end, p] = getStop(stops, percent); const value = start. map((value, i) => { value += p * (end[i] - value); return i === 3 ? uikitUtil.toFloat(value) : parseInt(value, 10); }). join(','); css[prop] = "rgba(" + value + ")"; }; } function parseColor(el, color) { return getCssValue(el, 'color', color). split(/[(),]/g). slice(1, -1). concat(1). slice(0, 4). map(uikitUtil.toFloat); } function filterFn(prop, el, stops) { if (stops.length === 1) { stops.unshift(0); } const unit = getUnit(stops) || { blur: 'px', hue: 'deg' }[prop] || '%'; prop = { fopacity: 'opacity', hue: 'hue-rotate' }[prop] || prop; stops = parseStops(stops); return (css, percent) => { const value = getValue(stops, percent); css.filter += " " + prop + "(" + (value + unit) + ")"; }; } function cssPropFn(prop, el, stops) { if (stops.length === 1) { stops.unshift(getCssValue(el, prop, '')); } stops = parseStops(stops); return (css, percent) => { css[prop] = getValue(stops, percent); }; } function strokeFn(prop, el, stops) { if (stops.length === 1) { stops.unshift(0); } const unit = getUnit(stops); const length = getMaxPathLength(el); stops = parseStops(stops.reverse(), (stop) => { stop = uikitUtil.toFloat(stop); return unit === '%' ? stop * length / 100 : stop; }); if (!stops.some((_ref) => {let [value] = _ref;return value;})) { return uikitUtil.noop; } uikitUtil.css(el, 'strokeDasharray', length); return (css, percent) => { css.strokeDashoffset = getValue(stops, percent); }; } function backgroundFn(prop, el, stops) { if (stops.length === 1) { stops.unshift(0); } prop = prop.substr(-1); const attr = prop === 'y' ? 'height' : 'width'; stops = parseStops(stops, (stop) => uikitUtil.toPx(stop, attr, el)); const bgPos = getCssValue(el, "background-position-" + prop, ''); return getCssValue(el, 'backgroundSize', '') === 'cover' ? backgroundCoverFn(prop, el, stops, bgPos, attr) : setBackgroundPosFn(prop, stops, bgPos); } function backgroundCoverFn(prop, el, stops, bgPos, attr) { const dimImage = getBackgroundImageDimensions(el); if (!dimImage.width) { return uikitUtil.noop; } const values = stops.map((_ref2) => {let [value] = _ref2;return value;}); const min = Math.min(...values); const max = Math.max(...values); const down = values.indexOf(min) < values.indexOf(max); const diff = max - min; let pos = (down ? -diff : 0) - (down ? min : max); const dimEl = { width: el.offsetWidth, height: el.offsetHeight }; const baseDim = uikitUtil.Dimensions.cover(dimImage, dimEl); const span = baseDim[attr] - dimEl[attr]; if (span < diff) { dimEl[attr] = baseDim[attr] + diff - span; } else if (span > diff) { const posPercentage = dimEl[attr] / uikitUtil.toPx(bgPos, attr, el, true); if (posPercentage) { pos -= (span - diff) / posPercentage; } } const dim = uikitUtil.Dimensions.cover(dimImage, dimEl); const fn = setBackgroundPosFn(prop, stops, pos + "px"); return (css, percent) => { fn(css, percent); css.backgroundSize = dim.width + "px " + dim.height + "px"; css.backgroundRepeat = 'no-repeat'; }; } function setBackgroundPosFn(prop, stops, pos) { return function (css, percent) { css["background-position-" + prop] = "calc(" + pos + " + " + getValue(stops, percent) + "px)"; }; } const dimensions = {}; function getBackgroundImageDimensions(el) { const src = uikitUtil.css(el, 'backgroundImage').replace(/^none|url\(["']?(.+?)["']?\)$/, '$1'); if (dimensions[src]) { return dimensions[src]; } const image = new Image(); if (src) { image.src = src; if (!image.naturalWidth) { image.onload = () => { dimensions[src] = toDimensions(image); uikitUtil.trigger(el, uikitUtil.createEvent('load', false)); }; return toDimensions(image); } } return dimensions[src] = toDimensions(image); } function toDimensions(image) { return { width: image.naturalWidth, height: image.naturalHeight }; } function parseStops(stops, fn) {if (fn === void 0) {fn = uikitUtil.toFloat;} const result = []; const { length } = stops; let nullIndex = 0; for (let i = 0; i < length; i++) { let [value, percent] = uikitUtil.isString(stops[i]) ? stops[i].trim().split(' ') : [stops[i]]; value = fn(value); percent = percent ? uikitUtil.toFloat(percent) / 100 : null; if (i === 0) { if (percent === null) { percent = 0; } else if (percent) { result.push([value, 0]); } } else if (i === length - 1) { if (percent === null) { percent = 1; } else if (percent !== 1) { result.push([value, percent]); percent = 1; } } result.push([value, percent]); if (percent === null) { nullIndex++; } else if (nullIndex) { const leftPercent = result[i - nullIndex - 1][1]; const p = (percent - leftPercent) / (nullIndex + 1); for (let j = nullIndex; j > 0; j--) { result[i - j][1] = leftPercent + p * (nullIndex - j + 1); } nullIndex = 0; } } return result; } function getStop(stops, percent) { const index = uikitUtil.findIndex(stops.slice(1), (_ref3) => {let [, targetPercent] = _ref3;return percent <= targetPercent;}) + 1; return [ stops[index - 1][0], stops[index][0], (percent - stops[index - 1][1]) / (stops[index][1] - stops[index - 1][1])]; } function getValue(stops, percent) { const [start, end, p] = getStop(stops, percent); return uikitUtil.isNumber(start) ? start + Math.abs(start - end) * p * (start < end ? 1 : -1) : +end; } const unitRe = /^-?\d+(\S*)/; function getUnit(stops, defaultUnit) { for (const stop of stops) { const match = stop.match == null ? void 0 : stop.match(unitRe); if (match) { return match[1]; } } return defaultUnit; } function getCssValue(el, prop, value) { const prev = el.style[prop]; const val = uikitUtil.css(uikitUtil.css(el, prop, value), prop); el.style[prop] = prev; return val; } function fillObject(keys, value) { return keys.reduce((data, prop) => { data[prop] = value; return data; }, {}); } var Component = { mixins: [Parallax, Resize, Scroll], props: { target: String, viewport: Number, // Deprecated easing: Number, start: String, end: String }, data: { target: false, viewport: 1, easing: 1, start: 0, end: 0 }, computed: { target(_ref, $el) {let { target } = _ref; return getOffsetElement(target && uikitUtil.query(target, $el) || $el); }, start(_ref2) {let { start } = _ref2; return uikitUtil.toPx(start, 'height', this.target, true); }, end(_ref3) {let { end, viewport } = _ref3; return uikitUtil.toPx( end || (viewport = (1 - viewport) * 100) && viewport + "vh+" + viewport + "%", 'height', this.target, true); } }, update: { read(_ref4, types) {let { percent } = _ref4; if (!types.has('scroll')) { percent = false; } if (!this.matchMedia) { return; } const prev = percent; percent = ease(uikitUtil.scrolledOver(this.target, this.start, this.end), this.easing); return { percent, style: prev === percent ? false : this.getCss(percent) }; }, write(_ref5) {let { style } = _ref5; if (!this.matchMedia) { this.reset(); return; } style && uikitUtil.css(this.$el, style); }, events: ['scroll', 'resize'] } }; function ease(percent, easing) { return easing >= 0 ? Math.pow(percent, easing + 1) : 1 - Math.pow(1 - percent, -easing + 1); } // SVG elements do not inherit from HTMLElement function getOffsetElement(el) { return el ? 'offsetTop' in el ? el : getOffsetElement(uikitUtil.parent(el)) : document.documentElement; } if (typeof window !== 'undefined' && window.UIkit) { window.UIkit.component('parallax', Component); } return Component; }));