mirror of
https://github.com/ruvnet/RuVector.git
synced 2026-05-25 15:03:46 +00:00
Major additions: - Complete Next.js studio application with 1600+ components - Docker support (Dockerfile.combined, docker-compose.yml) - GCP deployment documentation and benchmarks - SQL benchmark scripts for performance testing - Sentry integration for monitoring - Comprehensive test suite and mocks Studio features: - Dashboard and admin interfaces - Data visualization components - Authentication and user management - API integration with RuVector backend - Static data and public assets 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
45 lines
1.1 KiB
TypeScript
45 lines
1.1 KiB
TypeScript
import { useIsomorphicLayoutEffect } from 'common'
|
|
import { useRef } from 'react'
|
|
|
|
// Source: https://youtu.be/3kDVachh-BM
|
|
|
|
let stashedTime: number | null = null
|
|
|
|
export function useSynchronizedAnimation<T>(name: string) {
|
|
const ref = useRef<T>(null)
|
|
|
|
useIsomorphicLayoutEffect(() => {
|
|
const animations = document
|
|
.getAnimations()
|
|
.filter(
|
|
(animation) => animation instanceof CSSAnimation && animation.animationName === 'shimmer'
|
|
)
|
|
|
|
const myAnimation = animations.find(
|
|
(animation) =>
|
|
animation.effect instanceof KeyframeEffect && animation.effect.target === ref.current
|
|
)
|
|
|
|
if (myAnimation === undefined) {
|
|
return
|
|
}
|
|
|
|
const leadAnimation = animations[0]
|
|
|
|
if (myAnimation === leadAnimation && stashedTime) {
|
|
myAnimation.currentTime = stashedTime
|
|
}
|
|
|
|
if (myAnimation !== leadAnimation) {
|
|
myAnimation.currentTime = leadAnimation.currentTime
|
|
}
|
|
|
|
return () => {
|
|
if (myAnimation === leadAnimation && myAnimation.currentTime) {
|
|
stashedTime = Number(myAnimation.currentTime)
|
|
}
|
|
}
|
|
}, [])
|
|
|
|
return ref
|
|
}
|