/*! @license ScrollReveal v4.0.1 Copyright 2018 Fisssion LLC. Licensed under the GNU General Public License 3.0 for compatible open source projects and non-commercial use. For commercial sites, themes, projects, and applications, keep your source code private/proprietary by purchasing a commercial license from https://scrollrevealjs.org/ */ import $ from 'tealight'; import { parse, multiply, rotateX, rotateY, rotateZ, scale, translateX, translateY } from 'rematrix'; import raf from 'miniraf'; var defaults = { delay: 0, distance: '0', duration: 600, easing: 'cubic-bezier(0.5, 0, 0, 1)', interval: 0, opacity: 0, origin: 'bottom', rotate: { x: 0, y: 0, z: 0 }, scale: 1, cleanup: true, container: document.documentElement, desktop: true, mobile: true, reset: false, useDelay: 'always', viewFactor: 0.0, viewOffset: { top: 0, right: 0, bottom: 0, left: 0 }, afterReset: function afterReset() {}, afterReveal: function afterReveal() {}, beforeReset: function beforeReset() {}, beforeReveal: function beforeReveal() {} } function failure() { var root = document.documentElement; root.classList.remove('sr'); return { clean: function clean() {}, destroy: function destroy() {}, reveal: function reveal() {}, sync: function sync() {}, get noop() { return true } } } function success() { var html = document.documentElement; var body = document.body; html.classList.add('sr'); if (body) { body.style.height = '100%'; } else { document.addEventListener('DOMContentLoaded', function () { body.style.height = '100%'; }); } } var mount = { success: success, failure: failure } function isObject(x) { return ( x !== null && x instanceof Object && (x.constructor === Object || Object.prototype.toString.call(x) === '[object Object]') ) } function each(collection, callback) { if (isObject(collection)) { var keys = Object.keys(collection); return keys.forEach(function (key) { return callback(collection[key], key, collection); }) } if (collection instanceof Array) { return collection.forEach(function (item, i) { return callback(item, i, collection); }) } throw new TypeError('Expected either an array or object literal.') } function logger(message) { var details = [], len = arguments.length - 1; while ( len-- > 0 ) details[ len ] = arguments[ len + 1 ]; if (this.constructor.debug && console) { var report = "%cScrollReveal: " + message; details.forEach(function (detail) { return (report += "\n — " + detail); }); console.log(report, 'color: #ea654b;'); // eslint-disable-line no-console } } function rinse() { var this$1 = this; var struct = function () { return ({ active: [], stale: [] }); }; var elementIds = struct(); var sequenceIds = struct(); var containerIds = struct(); /** * Take stock of active element IDs. */ try { each($('[data-sr-id]'), function (node) { var id = parseInt(node.getAttribute('data-sr-id')); elementIds.active.push(id); }); } catch (e) { throw e } /** * Destroy stale elements. */ each(this.store.elements, function (element) { if (elementIds.active.indexOf(element.id) === -1) { elementIds.stale.push(element.id); } }); each(elementIds.stale, function (staleId) { return delete this$1.store.elements[staleId]; }); /** * Take stock of active container and sequence IDs. */ each(this.store.elements, function (element) { if (containerIds.active.indexOf(element.containerId) === -1) { containerIds.active.push(element.containerId); } if (element.hasOwnProperty('sequence')) { if (sequenceIds.active.indexOf(element.sequence.id) === -1) { sequenceIds.active.push(element.sequence.id); } } }); /** * Destroy stale containers. */ each(this.store.containers, function (container) { if (containerIds.active.indexOf(container.id) === -1) { containerIds.stale.push(container.id); } }); each(containerIds.stale, function (staleId) { var stale = this$1.store.containers[staleId].node; stale.removeEventListener('scroll', this$1.delegate); stale.removeEventListener('resize', this$1.delegate); delete this$1.store.containers[staleId]; }); /** * Destroy stale sequences. */ each(this.store.sequences, function (sequence) { if (sequenceIds.active.indexOf(sequence.id) === -1) { sequenceIds.stale.push(sequence.id); } }); each(sequenceIds.stale, function (staleId) { return delete this$1.store.sequences[staleId]; }); } function clean(target) { var this$1 = this; var dirty; try { each($(target), function (node) { var id = node.getAttribute('data-sr-id'); if (id !== null) { dirty = true; var element = this$1.store.elements[id]; if (element.callbackTimer) { window.clearTimeout(element.callbackTimer.clock); } node.setAttribute('style', element.styles.inline.generated); node.removeAttribute('data-sr-id'); delete this$1.store.elements[id]; } }); } catch (e) { return logger.call(this, 'Clean failed.', e.message) } if (dirty) { try { rinse.call(this); } catch (e) { return logger.call(this, 'Clean failed.', e.message) } } } function destroy() { var this$1 = this; /** * Remove all generated styles and element ids */ each(this.store.elements, function (element) { element.node.setAttribute('style', element.styles.inline.generated); element.node.removeAttribute('data-sr-id'); }); /** * Remove all event listeners. */ each(this.store.containers, function (container) { var target = container.node === document.documentElement ? window : container.node; target.removeEventListener('scroll', this$1.delegate); target.removeEventListener('resize', this$1.delegate); }); /** * Clear all data from the store */ this.store = { containers: {}, elements: {}, history: [], sequences: {} }; } var getPrefixedCssProp = (function () { var properties = {}; var style = document.documentElement.style; function getPrefixedCssProperty(name, source) { if ( source === void 0 ) source = style; if (name && typeof name === 'string') { if (properties[name]) { return properties[name] } if (typeof source[name] === 'string') { return (properties[name] = name) } if (typeof source[("-webkit-" + name)] === 'string') { return (properties[name] = "-webkit-" + name) } throw new RangeError(("Unable to find \"" + name + "\" style property.")) } throw new TypeError('Expected a string.') } getPrefixedCssProperty.clearCache = function () { return (properties = {}); }; return getPrefixedCssProperty })(); function style(element) { var computed = window.getComputedStyle(element.node); var position = computed.position; var config = element.config; /** * Generate inline styles */ var inline = {}; var inlineStyle = element.node.getAttribute('style') || ''; var inlineMatch = inlineStyle.match(/[\w-]+\s*:\s*[^;]+\s*/gi) || []; inline.computed = inlineMatch ? inlineMatch.map(function (m) { return m.trim(); }).join('; ') + ';' : ''; inline.generated = inlineMatch.some(function (m) { return m.match(/visibility\s?:\s?visible/i); }) ? inline.computed : inlineMatch.concat( ['visibility: visible']).map(function (m) { return m.trim(); }).join('; ') + ';'; /** * Generate opacity styles */ var computedOpacity = parseFloat(computed.opacity); var configOpacity = !isNaN(parseFloat(config.opacity)) ? parseFloat(config.opacity) : parseFloat(computed.opacity); var opacity = { computed: computedOpacity !== configOpacity ? ("opacity: " + computedOpacity + ";") : '', generated: computedOpacity !== configOpacity ? ("opacity: " + configOpacity + ";") : '' }; /** * Generate transformation styles */ var transformations = []; if (parseFloat(config.distance)) { var axis = config.origin === 'top' || config.origin === 'bottom' ? 'Y' : 'X'; /** * Let’s make sure our our pixel distances are negative for top and left. * e.g. { origin: 'top', distance: '25px' } starts at `top: -25px` in CSS. */ var distance = config.distance; if (config.origin === 'top' || config.origin === 'left') { distance = /^-/.test(distance) ? distance.substr(1) : ("-" + distance); } var ref = distance.match(/(^-?\d+\.?\d?)|(em$|px$|%$)/g); var value = ref[0]; var unit = ref[1]; switch (unit) { case 'em': distance = parseInt(computed.fontSize) * value; break case 'px': distance = value; break case '%': /** * Here we use `getBoundingClientRect` instead of * the existing data attached to `element.geometry` * because only the former includes any transformations * current applied to the element. * * If that behavior ends up being unintuitive, this * logic could instead utilize `element.geometry.height` * and `element.geoemetry.width` for the distaince calculation */ distance = axis === 'Y' ? element.node.getBoundingClientRect().height * value / 100 : element.node.getBoundingClientRect().width * value / 100; break default: throw new RangeError('Unrecognized or missing distance unit.') } if (axis === 'Y') { transformations.push(translateY(distance)); } else { transformations.push(translateX(distance)); } } if (config.rotate.x) { transformations.push(rotateX(config.rotate.x)); } if (config.rotate.y) { transformations.push(rotateY(config.rotate.y)); } if (config.rotate.z) { transformations.push(rotateZ(config.rotate.z)); } if (config.scale !== 1) { if (config.scale === 0) { /** * The CSS Transforms matrix interpolation specification * basically disallows transitions of non-invertible * matrixes, which means browsers won't transition * elements with zero scale. * * That’s inconvenient for the API and developer * experience, so we simply nudge their value * slightly above zero; this allows browsers * to transition our element as expected. * * `0.0002` was the smallest number * that performed across browsers. */ transformations.push(scale(0.0002)); } else { transformations.push(scale(config.scale)); } } var transform = {}; if (transformations.length) { transform.property = getPrefixedCssProp('transform'); /** * The default computed transform value should be one of: * undefined || 'none' || 'matrix()' || 'matrix3d()' */ transform.computed = { raw: computed[transform.property], matrix: parse(computed[transform.property]) }; transformations.unshift(transform.computed.matrix); var product = transformations.reduce(multiply); transform.generated = { initial: ((transform.property) + ": matrix3d(" + (product.join(', ')) + ");"), final: ((transform.property) + ": matrix3d(" + (transform.computed.matrix.join( ', ' )) + ");") }; } else { transform.generated = { initial: '', final: '' }; } /** * Generate transition styles */ var transition = {}; if (opacity.generated || transform.generated.initial) { transition.property = getPrefixedCssProp('transition'); transition.computed = computed[transition.property]; transition.fragments = []; var delay = config.delay; var duration = config.duration; var easing = config.easing; if (opacity.generated) { transition.fragments.push({ delayed: ("opacity " + (duration / 1000) + "s " + easing + " " + (delay / 1000) + "s"), instant: ("opacity " + (duration / 1000) + "s " + easing + " 0s") }); } if (transform.generated.initial) { transition.fragments.push({ delayed: ((transform.property) + " " + (duration / 1000) + "s " + easing + " " + (delay / 1000) + "s"), instant: ((transform.property) + " " + (duration / 1000) + "s " + easing + " 0s") }); } /** * The default computed transition property should be one of: * undefined || '' || 'all 0s ease 0s' || 'all 0s 0s cubic-bezier()' */ if (transition.computed && !transition.computed.match(/all 0s/)) { transition.fragments.unshift({ delayed: transition.computed, instant: transition.computed }); } var composed = transition.fragments.reduce( function (composition, fragment, i) { composition.delayed += i === 0 ? fragment.delayed : (", " + (fragment.delayed)); composition.instant += i === 0 ? fragment.instant : (", " + (fragment.instant)); return composition }, { delayed: '', instant: '' } ); transition.generated = { delayed: ((transition.property) + ": " + (composed.delayed) + ";"), instant: ((transition.property) + ": " + (composed.instant) + ";") }; } else { transition.generated = { delayed: '', instant: '' }; } return { inline: inline, opacity: opacity, position: position, transform: transform, transition: transition } } function animate(element, force) { if ( force === void 0 ) force = {}; var pristine = force.pristine || this.pristine; var delayed = element.config.useDelay === 'always' || (element.config.useDelay === 'onload' && pristine) || (element.config.useDelay === 'once' && !element.seen); var shouldReveal = element.visible && !element.revealed; var shouldReset = !element.visible && element.revealed && element.config.reset; if (force.reveal || shouldReveal) { return triggerReveal.call(this, element, delayed) } if (force.reset || shouldReset) { return triggerReset.call(this, element) } } function triggerReveal(element, delayed) { var styles = [ element.styles.inline.generated, element.styles.opacity.computed, element.styles.transform.generated.final ]; if (delayed) { styles.push(element.styles.transition.generated.delayed); } else { styles.push(element.styles.transition.generated.instant); } element.revealed = element.seen = true; element.node.setAttribute('style', styles.filter(function (s) { return s !== ''; }).join(' ')); registerCallbacks.call(this, element, delayed); } function triggerReset(element) { var styles = [ element.styles.inline.generated, element.styles.opacity.generated, element.styles.transform.generated.initial, element.styles.transition.generated.instant ]; element.revealed = false; element.node.setAttribute('style', styles.filter(function (s) { return s !== ''; }).join(' ')); registerCallbacks.call(this, element); } function registerCallbacks(element, isDelayed) { var this$1 = this; var duration = isDelayed ? element.config.duration + element.config.delay : element.config.duration; var beforeCallback = element.revealed ? element.config.beforeReveal : element.config.beforeReset; var afterCallback = element.revealed ? element.config.afterReveal : element.config.afterReset; var elapsed = 0; if (element.callbackTimer) { elapsed = Date.now() - element.callbackTimer.start; window.clearTimeout(element.callbackTimer.clock); } beforeCallback(element.node); element.callbackTimer = { start: Date.now(), clock: window.setTimeout(function () { afterCallback(element.node); element.callbackTimer = null; if (element.revealed && !element.config.reset && element.config.cleanup) { clean.call(this$1, element.node); } }, duration - elapsed) }; } var nextUniqueId = (function () { var uid = 0; return function () { return uid++; } })(); function sequence(element, pristine) { if ( pristine === void 0 ) pristine = this.pristine; /** * We first check if the element should reset. */ if (!element.visible && element.revealed && element.config.reset) { return animate.call(this, element, { reset: true }) } var seq = this.store.sequences[element.sequence.id]; var i = element.sequence.index; if (seq) { var visible = new SequenceModel(seq, 'visible', this.store); var revealed = new SequenceModel(seq, 'revealed', this.store); seq.models = { visible: visible, revealed: revealed }; /** * If the sequence has no revealed members, * then we reveal the first visible element * within that sequence. * * The sequence then cues a recursive call * in both directions. */ if (!revealed.body.length) { var nextId = seq.members[visible.body[0]]; var nextElement = this.store.elements[nextId]; if (nextElement) { cue.call(this, seq, visible.body[0], -1, pristine); cue.call(this, seq, visible.body[0], +1, pristine); return animate.call(this, nextElement, { reveal: true, pristine: pristine }) } } /** * If our element isn’t resetting, we check the * element sequence index against the head, and * then the foot of the sequence. */ if ( !seq.blocked.head && i === [].concat( revealed.head ).pop() && i >= [].concat( visible.body ).shift() ) { cue.call(this, seq, i, -1, pristine); return animate.call(this, element, { reveal: true, pristine: pristine }) } if ( !seq.blocked.foot && i === [].concat( revealed.foot ).shift() && i <= [].concat( visible.body ).pop() ) { cue.call(this, seq, i, +1, pristine); return animate.call(this, element, { reveal: true, pristine: pristine }) } } } function Sequence(interval) { var i = Math.abs(interval); if (!isNaN(i)) { this.id = nextUniqueId(); this.interval = Math.max(i, 16); this.members = []; this.models = {}; this.blocked = { head: false, foot: false }; } else { throw new RangeError('Invalid sequence interval.') } } function SequenceModel(seq, prop, store) { var this$1 = this; this.head = []; this.body = []; this.foot = []; each(seq.members, function (id, index) { var element = store.elements[id]; if (element && element[prop]) { this$1.body.push(index); } }); if (this.body.length) { each(seq.members, function (id, index) { var element = store.elements[id]; if (element && !element[prop]) { if (index < this$1.body[0]) { this$1.head.push(index); } else { this$1.foot.push(index); } } }); } } function cue(seq, i, direction, pristine) { var this$1 = this; var blocked = ['head', null, 'foot'][1 + direction]; var nextId = seq.members[i + direction]; var nextElement = this.store.elements[nextId]; seq.blocked[blocked] = true; setTimeout(function () { seq.blocked[blocked] = false; if (nextElement) { sequence.call(this$1, nextElement, pristine); } }, seq.interval); } function initialize() { var this$1 = this; rinse.call(this); each(this.store.elements, function (element) { var styles = [element.styles.inline.generated]; if (element.visible) { styles.push(element.styles.opacity.computed); styles.push(element.styles.transform.generated.final); } else { styles.push(element.styles.opacity.generated); styles.push(element.styles.transform.generated.initial); } element.node.setAttribute('style', styles.filter(function (s) { return s !== ''; }).join(' ')); }); each(this.store.containers, function (container) { var target = container.node === document.documentElement ? window : container.node; target.addEventListener('scroll', this$1.delegate); target.addEventListener('resize', this$1.delegate); }); /** * Manually invoke delegate once to capture * element and container dimensions, container * scroll position, and trigger any valid reveals */ this.delegate(); /** * Wipe any existing `setTimeout` now * that initialization has completed. */ this.initTimeout = null; } function isMobile(agent) { if ( agent === void 0 ) agent = navigator.userAgent; return /Android|iPhone|iPad|iPod/i.test(agent) } function deepAssign(target) { var sources = [], len = arguments.length - 1; while ( len-- > 0 ) sources[ len ] = arguments[ len + 1 ]; if (isObject(target)) { each(sources, function (source) { each(source, function (data, key) { if (isObject(data)) { if (!target[key] || !isObject(target[key])) { target[key] = {}; } deepAssign(target[key], data); } else { target[key] = data; } }); }); return target } else { throw new TypeError('Target must be an object literal.') } } function reveal(target, options, syncing) { var this$1 = this; if ( options === void 0 ) options = {}; if ( syncing === void 0 ) syncing = false; var containerBuffer = []; var sequence$$1; var interval = options.interval || defaults.interval; try { if (interval) { sequence$$1 = new Sequence(interval); } var nodes = $(target); if (!nodes.length) { throw new Error('Invalid reveal target.') } var elements = nodes.reduce(function (elementBuffer, elementNode) { var element = {}; var existingId = elementNode.getAttribute('data-sr-id'); if (existingId) { deepAssign(element, this$1.store.elements[existingId]); /** * In order to prevent previously generated styles * from throwing off the new styles, the style tag * has to be reverted to its pre-reveal state. */ element.node.setAttribute('style', element.styles.inline.computed); } else { element.id = nextUniqueId(); element.node = elementNode; element.seen = false; element.revealed = false; element.visible = false; } var config = deepAssign({}, element.config || this$1.defaults, options); if ((!config.mobile && isMobile()) || (!config.desktop && !isMobile())) { if (existingId) { clean.call(this$1, element); } return elementBuffer // skip elements that are disabled } var containerNode = $(config.container)[0]; if (!containerNode) { throw new Error('Invalid container.') } if (!containerNode.contains(elementNode)) { return elementBuffer // skip elements found outside the container } var containerId; { containerId = getContainerId( containerNode, containerBuffer, this$1.store.containers ); if (containerId === null) { containerId = nextUniqueId(); containerBuffer.push({ id: containerId, node: containerNode }); } } element.config = config; element.containerId = containerId; element.styles = style(element); if (sequence$$1) { element.sequence = { id: sequence$$1.id, index: sequence$$1.members.length }; sequence$$1.members.push(element.id); } elementBuffer.push(element); return elementBuffer }, []); /** * Modifying the DOM via setAttribute needs to be handled * separately from reading computed styles in the map above * for the browser to batch DOM changes (limiting reflows) */ each(elements, function (element) { this$1.store.elements[element.id] = element; element.node.setAttribute('data-sr-id', element.id); }); } catch (e) { return logger.call(this, 'Reveal failed.', e.message) } /** * Now that element set-up is complete... * Let’s commit any container and sequence data we have to the store. */ each(containerBuffer, function (container) { this$1.store.containers[container.id] = { id: container.id, node: container.node }; }); if (sequence$$1) { this.store.sequences[sequence$$1.id] = sequence$$1; } /** * If reveal wasn't invoked by sync, we want to * make sure to add this call to the history. */ if (syncing !== true) { this.store.history.push({ target: target, options: options }); /** * Push initialization to the event queue, giving * multiple reveal calls time to be interpreted. */ if (this.initTimeout) { window.clearTimeout(this.initTimeout); } this.initTimeout = window.setTimeout(initialize.bind(this), 0); } } function getContainerId(node) { var collections = [], len = arguments.length - 1; while ( len-- > 0 ) collections[ len ] = arguments[ len + 1 ]; var id = null; each(collections, function (collection) { each(collection, function (container) { if (id === null && container.node === node) { id = container.id; } }); }); return id } /** * Re-runs the reveal method for each record stored in history, * for capturing new content asynchronously loaded into the DOM. */ function sync() { var this$1 = this; each(this.store.history, function (record) { reveal.call(this$1, record.target, record.options, true); }); initialize.call(this); } var polyfill = function (x) { return (x > 0) - (x < 0) || +x; }; var mathSign = Math.sign || polyfill function getGeometry(target, isContainer) { /** * We want to ignore padding and scrollbars for container elements. * More information here: https://goo.gl/vOZpbz */ var height = isContainer ? target.node.clientHeight : target.node.offsetHeight; var width = isContainer ? target.node.clientWidth : target.node.offsetWidth; var offsetTop = 0; var offsetLeft = 0; var node = target.node; do { if (!isNaN(node.offsetTop)) { offsetTop += node.offsetTop; } if (!isNaN(node.offsetLeft)) { offsetLeft += node.offsetLeft; } node = node.offsetParent; } while (node) return { bounds: { top: offsetTop, right: offsetLeft + width, bottom: offsetTop + height, left: offsetLeft }, height: height, width: width } } function getScrolled(container) { var top, left; if (container.node === document.documentElement) { top = window.pageYOffset; left = window.pageXOffset; } else { top = container.node.scrollTop; left = container.node.scrollLeft; } return { top: top, left: left } } function isElementVisible(element) { if ( element === void 0 ) element = {}; var container = this.store.containers[element.containerId]; if (!container) { return } var viewFactor = Math.max(0, Math.min(1, element.config.viewFactor)); var viewOffset = element.config.viewOffset; var elementBounds = { top: element.geometry.bounds.top + element.geometry.height * viewFactor, right: element.geometry.bounds.right - element.geometry.width * viewFactor, bottom: element.geometry.bounds.bottom - element.geometry.height * viewFactor, left: element.geometry.bounds.left + element.geometry.width * viewFactor }; var containerBounds = { top: container.geometry.bounds.top + container.scroll.top + viewOffset.top, right: container.geometry.bounds.right + container.scroll.left - viewOffset.right, bottom: container.geometry.bounds.bottom + container.scroll.top - viewOffset.bottom, left: container.geometry.bounds.left + container.scroll.left + viewOffset.left }; return ( (elementBounds.top < containerBounds.bottom && elementBounds.right > containerBounds.left && elementBounds.bottom > containerBounds.top && elementBounds.left < containerBounds.right) || element.styles.position === 'fixed' ) } function delegate( event, elements ) { var this$1 = this; if ( event === void 0 ) event = { type: 'init' }; if ( elements === void 0 ) elements = this.store.elements; raf(function () { var stale = event.type === 'init' || event.type === 'resize'; each(this$1.store.containers, function (container) { if (stale) { container.geometry = getGeometry.call(this$1, container, true); } var scroll = getScrolled.call(this$1, container); if (container.scroll) { container.direction = { x: mathSign(scroll.left - container.scroll.left), y: mathSign(scroll.top - container.scroll.top) }; } container.scroll = scroll; }); /** * Due to how the sequencer is implemented, it’s * important that we update the state of all * elements, before any animation logic is * evaluated (in the second loop below). */ each(elements, function (element) { if (stale) { element.geometry = getGeometry.call(this$1, element); } element.visible = isElementVisible.call(this$1, element); }); each(elements, function (element) { if (element.sequence) { sequence.call(this$1, element); } else { animate.call(this$1, element); } }); this$1.pristine = false; }); } function transformSupported() { var style = document.documentElement.style; return 'transform' in style || 'WebkitTransform' in style } function transitionSupported() { var style = document.documentElement.style; return 'transition' in style || 'WebkitTransition' in style } var version = "4.0.1"; var boundDelegate; var boundDestroy; var boundReveal; var boundClean; var boundSync; var config; var debug; var instance; function ScrollReveal(options) { if ( options === void 0 ) options = {}; var invokedWithoutNew = typeof this === 'undefined' || Object.getPrototypeOf(this) !== ScrollReveal.prototype; if (invokedWithoutNew) { return new ScrollReveal(options) } if (!ScrollReveal.isSupported()) { logger.call(this, 'Instantiation failed.', 'This browser is not supported.'); return mount.failure() } var buffer; try { buffer = config ? deepAssign({}, config, options) : deepAssign({}, defaults, options); } catch (e) { logger.call(this, 'Invalid configuration.', e.message); return mount.failure() } try { var container = $(buffer.container)[0]; if (!container) { throw new Error('Invalid container.') } } catch (e) { logger.call(this, e.message); return mount.failure() } config = buffer; if ((!config.mobile && isMobile()) || (!config.desktop && !isMobile())) { logger.call( this, 'This device is disabled.', ("desktop: " + (config.desktop)), ("mobile: " + (config.mobile)) ); return mount.failure() } mount.success(); this.store = { containers: {}, elements: {}, history: [], sequences: {} }; this.pristine = true; boundDelegate = boundDelegate || delegate.bind(this); boundDestroy = boundDestroy || destroy.bind(this); boundReveal = boundReveal || reveal.bind(this); boundClean = boundClean || clean.bind(this); boundSync = boundSync || sync.bind(this); Object.defineProperty(this, 'delegate', { get: function () { return boundDelegate; } }); Object.defineProperty(this, 'destroy', { get: function () { return boundDestroy; } }); Object.defineProperty(this, 'reveal', { get: function () { return boundReveal; } }); Object.defineProperty(this, 'clean', { get: function () { return boundClean; } }); Object.defineProperty(this, 'sync', { get: function () { return boundSync; } }); Object.defineProperty(this, 'defaults', { get: function () { return config; } }); Object.defineProperty(this, 'version', { get: function () { return version; } }); Object.defineProperty(this, 'noop', { get: function () { return false; } }); return instance ? instance : (instance = this) } ScrollReveal.isSupported = function () { return transformSupported() && transitionSupported(); }; Object.defineProperty(ScrollReveal, 'debug', { get: function () { return debug || false; }, set: function (value) { return (debug = typeof value === 'boolean' ? value : debug); } }); ScrollReveal(); export default ScrollReveal;