1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | 1× 1× 1× 1× 1× 1× 1× 1× 1× 1× 1× 3× 3× 1× 3× 3× 1× 1× 3× 3× 3× 3× 3× 3× 3× 3× 3× 3× 3× 3× 3× 1× | import Ember from 'ember'; import get from 'ember-metal/get'; import set from 'ember-metal/set'; import Configuration from 'ember-ticketfly-accordion/configuration'; const { K: noop } = Ember; const addonAnimationSettings = Configuration.addonAnimationSettings || {}; const closeSettings = addonAnimationSettings.panelClose || {}; const openSettings = addonAnimationSettings.panelOpen || {}; const DURATION__CLOSE_PANEL = closeSettings.duration || 390; const DURATION__OPEN_PANEL = openSettings.duration || 300; const EASING__CLOSE_PANEL = closeSettings.easing || 'cubic-bezier(0.645, 0.045, 0.355, 1.000)'; // ease-in-out-cubic const EASING__OPEN_PANEL = openSettings.easing || 'cubic-bezier(0.215, 0.610, 0.355, 1)'; // ease-out-cubic const OPEN_TIMING = { duration: DURATION__OPEN_PANEL, easing: EASING__OPEN_PANEL, fill: 'forwards' }; const CLOSE_TIMING = { duration: DURATION__CLOSE_PANEL, easing: EASING__CLOSE_PANEL, fill: 'forwards' }; function makeStartingOpenEffect(elem) { const position = 'absolute'; return new KeyframeEffect( elem, [ // fun trick that will allow us to measure the element's final height before animating it there from `display: none` { position, visibility: 'inherit' }, { position, visibility: 'hidden' } ], { duration: 0 } ); } function makeSlideDownEffect(panelBodyElem) { const { height, paddingTop, paddingBottom } = getComputedStyle(panelBodyElem); return new KeyframeEffect( panelBodyElem, [ { visibility: 'visible', height: '0px', paddingTop: '0px', paddingBottom: '0px', overflow: 'hidden', opacity: 0 }, { visibility: 'visible', height: `${height}`, paddingTop: `${paddingTop}`, paddingBottom: `${paddingBottom}`, overflow: 'hidden', opacity: 1 } ], OPEN_TIMING ); } function makeClosingEffect(panelBodyElem, { height, paddingTop, paddingBottom }) { return new KeyframeEffect( panelBodyElem, [ { height, paddingTop, paddingBottom, overflow: 'hidden', visibility: 'visible', opacity: 1 }, { height: '0px', paddingTop: '0px', paddingBottom: '0px', overflow: 'hidden', visibility: 'hidden', opacity: 0 } ], CLOSE_TIMING ); } function animatePanelOpen(panelComponent, onComplete = noop) { const panelBodyComponent = get(panelComponent, 'panelBody'); const panelBodyElem = get(panelBodyComponent, 'element'); const startingEffect = makeStartingOpenEffect(panelBodyElem); const startingAnimation = new Animation(startingEffect, document.timeline); startingAnimation.onfinish = function _initialPanelOpenOnfinish() { const slideDownEffect = makeSlideDownEffect(panelBodyElem); const slideDownAnimation = new Animation(slideDownEffect, document.timeline); slideDownAnimation.onfinish = function _finalPanelOpenOnfinish() { Iif (!get(panelBodyComponent, 'isDestroyed')) { onComplete(panelComponent); } }; slideDownAnimation.play(); }; set(panelBodyComponent, 'isPanelExpanded', true); startingAnimation.play(); return startingAnimation; } function animatePanelClosed(panelComponent, onComplete = noop) { const panelBodyComponent = get(panelComponent, 'panelBody'); const panelBodyElem = get(panelBodyComponent, 'element'); const { height, paddingTop, paddingBottom } = getComputedStyle(panelBodyElem); const effect = makeClosingEffect(panelBodyElem, { height, paddingTop, paddingBottom }); const animation = new Animation(effect, document.timeline); animation.onfinish = function _panelCloseOnfinish() { // Before removing the panel body element from the accessibility tree and hiding // setting it to `display: none`, we need to restore its measurements so that they // can be read properly on the next "show" panelBodyElem.animate( [ { height: '0px', paddingTop: '0px', paddingBottom: '0px', visibility: 'hidden' }, { height, paddingTop, paddingBottom, visibility: 'visible' } ], { duration: 0.0001, fill: 'forwards' } ); if (!get(panelBodyComponent, 'isDestroyed')) { set(panelBodyComponent, 'isPanelExpanded', false); onComplete(panelComponent); } }; animation.play(); return animation; } export { animatePanelOpen, animatePanelClosed }; |