1const ACTIVE_ANIMATIONS = new WeakMap(); 2const REDUCED_MOTION_QUERY = "(prefers-reduced-motion: reduce)"; 3 4export function shouldAnimateNumberChange(previousValue, nextValue) { 5 const previous = String(previousValue ?? "").trim(); 6 const next = String(nextValue ?? "").trim(); 7 return previous !== next && /\d/.test(previous) && /\d/.test(next); 8} 9 10function prefersReducedMotion(element) { 11 const view = element?.ownerDocument?.defaultView; 12 return Boolean(view?.matchMedia?.(REDUCED_MOTION_QUERY).matches); 13} 14 15export function setAnimatedNumberText(element, nextValue, { duration = 420 } = {}) { 16 if (!element) return false; 17 const next = String(nextValue ?? ""); 18 const previous = String(element.textContent ?? ""); 19 const initialized = element.dataset?.numberMotionReady === "true"; 20 21 if (element.dataset) element.dataset.numberMotionReady = "true"; 22 if (previous === next) return false; 23 24 const previousAnimation = ACTIVE_ANIMATIONS.get(element); 25 if (previousAnimation) { 26 try { previousAnimation.cancel(); } catch {} 27 ACTIVE_ANIMATIONS.delete(element); 28 } 29 element.textContent = next; 30 31 if (!initialized || !shouldAnimateNumberChange(previous, next) || prefersReducedMotion(element) || typeof element.animate !== "function") { 32 return false; 33 } 34 35 const animation = element.animate([ 36 { opacity: 0.45, transform: "translateY(0.16em) scale(0.985)", filter: "blur(0.35px)" }, 37 { opacity: 1, transform: "translateY(0) scale(1)", filter: "blur(0)" } 38 ], { 39 duration: Math.max(1, Number(duration) || 420), 40 easing: "cubic-bezier(.2,.8,.2,1)", 41 fill: "both" 42 }); 43 ACTIVE_ANIMATIONS.set(element, animation); 44 if (element.dataset) element.dataset.numberMotionActive = "true"; 45 46 const cleanup = () => { 47 if (ACTIVE_ANIMATIONS.get(element) !== animation) return; 48 ACTIVE_ANIMATIONS.delete(element); 49 if (element.dataset) delete element.dataset.numberMotionActive; 50 }; 51 if (animation.finished?.then) animation.finished.then(cleanup, cleanup); 52 return true; 53}
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.