UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

330 lines 11.9 kB
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty"; function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } export default class HeightAnimation { constructor(opts = {}) { _defineProperty(this, "state", void 0); _defineProperty(this, "isInBrowser", void 0); _defineProperty(this, "onStartStack", []); _defineProperty(this, "onEndStack", []); _defineProperty(this, "events", []); _defineProperty(this, "opts", { animate: true }); _defineProperty(this, "elem", void 0); _defineProperty(this, "reqId1", void 0); _defineProperty(this, "reqId2", void 0); _defineProperty(this, "resizeTimeout", void 0); _defineProperty(this, "timeouts", []); _defineProperty(this, "firstTime", 0); _defineProperty(this, "startTime", 0); _defineProperty(this, "duration", 0); _defineProperty(this, "isAnimating", void 0); _defineProperty(this, "__currentHeight", void 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 _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 { this.timeouts.push(setTimeout(() => listener(e), delay)); } } }; this.events.push(handleTransitionEnd); (_this$elem = this.elem) === null || _this$elem === void 0 ? void 0 : (_this$elem$addEventLi = _this$elem.addEventListener) === null || _this$elem$addEventLi === void 0 ? 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 ? void 0 : (_this$elem2$removeEve = _this$elem2.removeEventListener) === null || _this$elem2$removeEve === void 0 ? 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(_objectSpread(_objectSpread({}, 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 ? 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 ? 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) { this.onStartStack.push(fn); } onEnd(fn) { this.onEndStack.push(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; const cleanup = this.stopOuterAnimations(); this.reqId1 = window.requestAnimationFrame(() => { if (!this.elem || 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`; cleanup(); }); }); } 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 (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 (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) { this.setState('adjusted'); 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); } stopOuterAnimations() { const elements = []; const getCloses = elem => { var _elem$parentElement; return (_elem$parentElement = elem.parentElement) === null || _elem$parentElement === void 0 ? void 0 : _elem$parentElement.closest('.dnb-height-animation'); }; let elem = getCloses(this.elem); while (elem) { elements.push(elem); elem = getCloses(elem); } elements.forEach(elem => { elem.classList.add('dnb-height-animation--stop'); }); return () => { elements.forEach(elem => { if (elem) { elem.classList.remove('dnb-height-animation--stop'); } }); elements.length = 0; }; } 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