UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

301 lines 10.4 kB
import _defineProperty from "@babel/runtime-corejs3/helpers/esm/defineProperty"; import _pushInstanceProperty from "core-js-pure/stable/instance/push.js"; export default class HeightAnimation { constructor(opts = {}) { _defineProperty(this, "onStartStack", []); _defineProperty(this, "onEndStack", []); _defineProperty(this, "events", []); _defineProperty(this, "opts", { animate: true }); _defineProperty(this, "timeouts", []); _defineProperty(this, "firstTime", 0); _defineProperty(this, "startTime", 0); _defineProperty(this, "duration", 0); _defineProperty(this, "firstPaintStyle", { visibility: 'hidden', opacity: '0', height: 'auto' }); this.isInBrowser = typeof window !== 'undefined'; this.setState('init'); this.setOptions(opts); } callAnimationStart() { this.startTime = Date.now(); if (!this.firstTime) { this.firstTime = this.startTime; } if (this.onStartStack) { this.onStartStack.forEach(fn => { if (typeof fn === 'function') { fn(this.state); } }); } } callAnimationEnd() { this.isAnimating = false; if (this.state !== 'opened') { delete this.__currentHeight; } this.removeEndEvents(); if (this.onEndStack) { this.onEndStack.forEach(fn => { if (typeof fn === 'function') { fn(this.state); } }); } } addEndEvent(listener) { var _context2, _this$elem, _this$elem$addEventLi; this.removeEndEvents(); const handleTransitionEnd = e => { if (this.canFinish()) { listener(e); } else { const delay = this.duration - (Date.now() - this.startTime); if (delay === -1) { listener(e); } else { var _context; _pushInstanceProperty(_context = this.timeouts).call(_context, setTimeout(() => listener(e), delay)); } } }; _pushInstanceProperty(_context2 = this.events).call(_context2, handleTransitionEnd); (_this$elem = this.elem) === null || _this$elem === void 0 || (_this$elem$addEventLi = _this$elem.addEventListener) === null || _this$elem$addEventLi === void 0 || _this$elem$addEventLi.call(_this$elem, 'transitionend', handleTransitionEnd); } removeEndEvents() { this.events.forEach(listener => { var _this$elem2, _this$elem2$removeEve; (_this$elem2 = this.elem) === null || _this$elem2 === void 0 || (_this$elem2$removeEve = _this$elem2.removeEventListener) === null || _this$elem2$removeEve === void 0 || _this$elem2$removeEve.call(_this$elem2, 'transitionend', listener); }); this.events = []; } setElement(elem) { var _this$elem3, _globalThis$animation; this.elem = elem || typeof document !== 'undefined' && document.createElement('div'); if (String((_this$elem3 = this.elem) === null || _this$elem3 === void 0 ? void 0 : _this$elem3.nodeName).toLowerCase() === 'td') { this.elem = this.elem.parentElement; } this.duration = (_globalThis$animation = globalThis.animationDuration) !== null && _globalThis$animation !== void 0 ? _globalThis$animation : parseFloat(window.getComputedStyle(this.elem).transitionDuration) * 1000 || 400; } setState(state) { this.state = Object.freeze(state); } setOptions(opts) { this.opts = Object.freeze({ ...this.opts, ...opts }); } getOptions() { return this.opts; } remove() { this.stop(); this.removeEndEvents(); this.setState('init'); this.isAnimating = false; this.onEndStack = []; this.onStartStack = []; this.__currentHeight = undefined; this.elem = undefined; } setAsOpen() { if (this.state === 'opened') { return; } this.setState('opening'); this.callAnimationStart(); this.setState('opened'); this.callAnimationEnd(); } setAsClosed() { if (this.state === 'closed') { return; } this.setState('closing'); this.callAnimationStart(); this.setState('closed'); this.callAnimationEnd(); } getHeight() { var _this$withFallback; return (_this$withFallback = this.withFallback(this.elem, 'clientHeight')) !== null && _this$withFallback !== void 0 ? _this$withFallback : null; } getUnknownHeight() { var _this$elem$parentNode, _this$withFallback2, _this$withFallback3, _clonedElem$parentNod; if (!this.elem) { return null; } if (this.isAnimating && typeof this.__currentHeight !== 'undefined') { return this.__currentHeight; } const clonedElem = this.elem.cloneNode(true); const inputs = clonedElem.querySelectorAll('input'); inputs.forEach(input => { input.removeAttribute('name'); input.removeAttribute('id'); }); for (const key in this.firstPaintStyle) { clonedElem.style[key] = this.firstPaintStyle[key]; } clonedElem.style.position = 'absolute'; (_this$elem$parentNode = this.elem.parentNode) === null || _this$elem$parentNode === void 0 || _this$elem$parentNode.insertBefore(clonedElem, this.elem.nextSibling); const elemWidth = this.elem.clientWidth; const clonedWidth = (_this$withFallback2 = this.withFallback(clonedElem, 'clientWidth', 'data-width')) !== null && _this$withFallback2 !== void 0 ? _this$withFallback2 : 0; if (clonedWidth > elemWidth) { clonedElem.style.width = `${elemWidth}px`; } const height = (_this$withFallback3 = this.withFallback(this.elem, 'clientHeight', 'data-height')) !== null && _this$withFallback3 !== void 0 ? _this$withFallback3 : null; (_clonedElem$parentNod = clonedElem.parentNode) === null || _clonedElem$parentNod === void 0 || _clonedElem$parentNod.removeChild(clonedElem); if (height) { this.__currentHeight = height; } return height; } withFallback(elem, key, fallback) { const val = fallback && elem.hasAttribute(fallback) ? parseFloat(elem.getAttribute(fallback)) : elem === null || elem === void 0 ? void 0 : elem[key]; if (isNaN(val)) { return null; } return val; } onStart(fn) { var _context3; _pushInstanceProperty(_context3 = this.onStartStack).call(_context3, fn); } onEnd(fn) { var _context4; _pushInstanceProperty(_context4 = this.onEndStack).call(_context4, fn); } start(fromHeight, toHeight) { if (!this.elem || !(this.isInBrowser && typeof window.requestAnimationFrame === 'function')) { return; } const opts = this.getOptions(); if (opts.animate === false) { return; } this.stop(); this.isAnimating = true; this.reqId1 = window.requestAnimationFrame(() => { if (!this.elem || toHeight !== 0 && this.elem.classList.contains('dnb-height-animation--stop')) { return; } this.elem.style.height = `${fromHeight}px`; this.reqId2 = window.requestAnimationFrame(() => { if (!this.elem) { return; } this.elem.style.height = `${toHeight}px`; }); }); } stop() { this.timeouts.forEach(id => clearTimeout(id)); this.timeouts = []; if (this.isInBrowser && typeof window.requestAnimationFrame === 'function') { window.cancelAnimationFrame(this.reqId1); window.cancelAnimationFrame(this.reqId2); } } open() { if (this.state === 'opened' || this.state === 'opening' || this.shouldBypassAnimation()) { this.setAsOpen(); return; } this.setState('opening'); this.callAnimationStart(); const toHeight = this.getUnknownHeight(); this.addEndEvent(e => { if (this.state === 'opening' && e.target === e.currentTarget || !e.currentTarget) { if (this.elem) { this.elem.style.overflowY = ''; } this.setState('opened'); this.readjust(); } }); this.start(0, toHeight); } close() { if (this.state === 'closed' || this.state === 'closing' || this.shouldBypassAnimation()) { this.setAsClosed(); return; } this.setState('closing'); this.callAnimationStart(); const fromHeight = this.getHeight(); this.addEndEvent(e => { if (this.state === 'closing' && e.target === e.currentTarget || !e.currentTarget) { if (this.elem) { this.elem.style.visibility = 'hidden'; this.elem.style.overflowY = 'clip'; } this.setState('closed'); this.callAnimationEnd(); } }); this.start(fromHeight, 0); } adjustTo(fromHeight = null, toHeight = null) { const opts = this.getOptions(); if (!this.elem || opts.animate === false || this.state === 'opening' || this.state === 'closing') { return; } if (fromHeight === null) { fromHeight = this.getHeight(); } if (toHeight === null) { toHeight = this.getUnknownHeight(); } if (fromHeight === toHeight) { return; } this.setState('adjusting'); this.callAnimationStart(); this.addEndEvent(e => { if (this.state === 'adjusting' && (e.target === e.currentTarget || !e.currentTarget)) { if (this.elem) { this.elem.style.height = 'auto'; } this.setState('adjusted'); } this.callAnimationEnd(); }); this.start(fromHeight, toHeight); } readjust() { const endHeight = this.getHeight(); if (this.elem) { this.elem.style.height = 'auto'; } this.__currentHeight = undefined; const newHeight = this.getUnknownHeight(); if (endHeight !== newHeight) { this.adjustTo(endHeight, newHeight); } else { this.callAnimationEnd(); } } canFinish() { var _globalThis$animation2; return Boolean(this.startTime && Date.now() - this.startTime > ((_globalThis$animation2 = globalThis.animationDuration) !== null && _globalThis$animation2 !== void 0 ? _globalThis$animation2 : this.duration)); } shouldBypassAnimation() { var _globalThis$bypassTim; const opts = this.getOptions(); if (!this.elem || opts.animate === false) { return true; } if (this.isInBrowser && (globalThis.IS_TEST || globalThis.bypassTime === -1)) { return false; } return Boolean(this.firstTime && Date.now() - this.firstTime < ((_globalThis$bypassTim = globalThis.bypassTime) !== null && _globalThis$bypassTim !== void 0 ? _globalThis$bypassTim : 100)); } } //# sourceMappingURL=HeightAnimationInstance.js.map