1(function () { 2 'use strict'; 3 4 var MOTION = { 5 blur: 4, 6 scaleFrom: 0.91, 7 stiffness: 220, 8 damping: 31 9 }; 10 11 var activeAnimations = new WeakMap(); 12 13 function prefersReducedMotion() { 14 return window.matchMedia && 15 window.matchMedia('(prefers-reduced-motion: reduce)').matches; 16 } 17 18 function getParts(modal) { 19 return { 20 backdrop: modal.querySelector('.portal-config-modal__backdrop'), 21 panel: modal.querySelector('.portal-config-modal__panel') 22 }; 23 } 24 25 function cancelActive(modal) { 26 var animations = activeAnimations.get(modal) || []; 27 28 animations.forEach(function (animation) { 29 animation.cancel(); 30 }); 31 32 activeAnimations.delete(modal); 33 } 34 35 function simulateSpring(startScale, endScale, startOpacity, endOpacity) { 36 var dt = 1 / 60; 37 var minDuration = 0.18; 38 var maxDuration = 0.52; 39 var scale = startScale; 40 var velocity = 0; 41 var elapsed = 0; 42 var frames = [{ 43 time: 0, 44 scale: startScale, 45 opacity: startOpacity 46 }]; 47 48 while (elapsed < maxDuration) { 49 var displacement = scale - endScale; 50 var acceleration = (-MOTION.stiffness * displacement) - (MOTION.damping * velocity); 51 52 velocity += acceleration * dt; 53 scale += velocity * dt; 54 elapsed += dt; 55 56 var progress = Math.abs(endScale - startScale) > 0.0001 57 ? (scale - startScale) / (endScale - startScale) 58 : 1; 59 progress = Math.max(0, Math.min(1, progress)); 60 61 frames.push({ 62 time: elapsed, 63 scale: scale, 64 opacity: startOpacity + ((endOpacity - startOpacity) * progress) 65 }); 66 67 if (elapsed >= minDuration && Math.abs(scale - endScale) < 0.001 && Math.abs(velocity) < 0.001) { 68 break; 69 } 70 } 71 72 frames[frames.length - 1] = { 73 time: elapsed, 74 scale: endScale, 75 opacity: endOpacity 76 }; 77 78 return { 79 duration: Math.max(1, Math.round(elapsed * 1000)), 80 frames: frames 81 }; 82 } 83 84 function buildKeyframes(simulation, includeTransform) { 85 var lastTime = simulation.frames[simulation.frames.length - 1].time || 1; 86 87 return simulation.frames.map(function (frame) { 88 var keyframe = { 89 offset: Math.max(0, Math.min(1, frame.time / lastTime)), 90 opacity: String(Math.max(0, Math.min(1, frame.opacity))) 91 }; 92 93 if (includeTransform) { 94 keyframe.transform = 'scale(' + frame.scale.toFixed(4) + ')'; 95 } 96 97 return keyframe; 98 }); 99 } 100 101 function finishWithoutAnimation(modal, opening) { 102 modal.classList.toggle('hidden', !opening); 103 modal.setAttribute('data-state', opening ? 'open' : 'closed'); 104 105 return Promise.resolve(); 106 } 107 108 function run(modal, opening) { 109 if (!(modal instanceof HTMLElement)) { 110 return Promise.resolve(); 111 } 112 113 cancelActive(modal); 114 115 var parts = getParts(modal); 116 if (!(parts.panel instanceof HTMLElement) || !(parts.backdrop instanceof HTMLElement)) { 117 return finishWithoutAnimation(modal, opening); 118 } 119 120 modal.style.setProperty('--portal-modal-backdrop-blur', MOTION.blur + 'px'); 121 modal.style.setProperty('--portal-modal-scale-from', String(MOTION.scaleFrom)); 122 123 if (prefersReducedMotion() || typeof parts.panel.animate !== 'function') { 124 return finishWithoutAnimation(modal, opening); 125 } 126 127 if (opening) { 128 modal.classList.remove('hidden'); 129 } 130 131 modal.setAttribute('data-state', opening ? 'opening' : 'closing'); 132 133 var simulation = opening 134 ? simulateSpring(MOTION.scaleFrom, 1, 0, 1) 135 : simulateSpring(1, MOTION.scaleFrom, 1, 0); 136 var timing = { 137 duration: simulation.duration, 138 easing: 'linear', 139 fill: 'both' 140 }; 141 var animations = [ 142 parts.backdrop.animate(buildKeyframes(simulation, false), timing), 143 parts.panel.animate(buildKeyframes(simulation, true), timing) 144 ]; 145 146 activeAnimations.set(modal, animations); 147 148 return Promise.allSettled(animations.map(function (animation) { 149 return animation.finished; 150 })).then(function () { 151 if (activeAnimations.get(modal) !== animations) { 152 return; 153 } 154 155 modal.setAttribute('data-state', opening ? 'open' : 'closed'); 156 modal.classList.toggle('hidden', !opening); 157 158 animations.forEach(function (animation) { 159 animation.cancel(); 160 }); 161 162 activeAnimations.delete(modal); 163 }); 164 } 165 166 window.PortalModalMotion = { 167 open: function (modal) { 168 return run(modal, true); 169 }, 170 close: function (modal) { 171 return run(modal, false); 172 } 173 }; 174})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.