
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
@qyu/anim-react
Advanced tools
React hooks for @qyu/anim-core to create and run declarative animations
// create scheduler for browser, for native or node, use (Date, setTimeout, clearTimeout)
const scheduler_raf = fscheduler_new_frame(performance, requestAnimationFrame, cancelAnimationFrame)
const App = () => {
const tracker = useMemo(() => signal_new_value(0), [])
// animation will incrementally update when config changes
const [natfreq, natfreq_set] = useState(1e-2)
// animation will incrementally update when target changes
const [width_target, width_target_set] = useState(500)
const ref_element = useRef<HTMLDivElement | null>(null)
// run animation with animation frames
useRunAnimInterval({
// for fscheduler look at @qyu/anim-core
scheduler: scheduler_raf,
// will treat child animations individually as much as posiible
// that means when one of children changes it's initial value it will restart without affecting unrelated animations
// if false (by default) - runner will treat animation as monolith
spread: true,
src: useAnimStyleMapSpring({
// target element
ref: useRefObject(ref_element),
// default config for animations
config: useInputDynamicSet({
natfreq,
dampratio: 0.1,
}),
// useInputDynamicSet means
properties: useInputDynamicSet({
height: transvalue_new_cssunit({ from: 0, target: 400, unit: "px" }),
// when widht_target updates - this animation will also update
// you can override default config
width: transvalue_new_cssunit({ from: 0, target: { target: width_target, natfreq: 1e-3 }, unit: "px" }),
// color animation
// property names are not transformed = need to preserve dashes
// use tracker param to track value of something
// no animation on green param
"background-color": transvalue_new_csscolor([[0, 200], 150, [0, 255, { tracker }], [0.2, 0.8]]),
transform: transvalue_new_csstransform({
// no animation on this one
translateX: "100px",
// specific config for property
scaleX: transvalue_new_cssnumber({
from: 1,
target: {
target: 1.6,
natfreq: 5e-3,
precision: {
velocity: 1e-4,
displacement: 1e-5
}
},
})
})
})
}),
})
return <>
<button onClick={() => { natfreq_set(natfreq_old => natfreq_old * 2) } }>
Increase natfreq {natfreq}
</button>
<button onClick={() => { width_target_set(width_target_old => width_target_old + 500) } }>
Increase width_target {width_target}
</button>
<div ref={ref_element} />
</>
}
Animation will continuosly update on path conditions change (for linear animation it's config), but restart on initial conditions change. This works for all types of animations
const scheduler_raf = fscheduler_new_frame(performance, requestAnimationFrame, cancelAnimationFrame)
const App = () => {
const [target, target_set] = useState(100)
const [velocity, velocity_set] = useState(1e-1)
// run animation with animation frames
useRunAnimInterval({
scheduler: scheduler_raf,
src: useAnimLine({
init: useInputConstant({
state: 0
}),
config: useInputDynamicSet({
target,
velocity,
effect: state => {
console.log("Animation Tick: ", state)
}
})
}),
})
return <>
<button onClick={() => { target_set(target_old => target_old + 100) } }>
Increase target {target}
</button>
<button onClick={() => { velocity_set(velocity_old => velocity_old * 2) } }>
Increase velocity {velocity}
</button>
</>
}
Animations take special kind of input created with useInput hooks
// will never update no matter what
useInputConstant(10)
// will update when dependencies change
// dependencies can be ignored, then it will update when provided value changes
// as it updates will return new value and consequentially restart the animation
useInputStatic(10, [])
// accepts signal as parameter, when value in signal changes sends update to dependent animations
useInputDynamic(useSignalValue(10, [deps]))
// the same as previous one, just merged into one
useInputDynamicSet(10, [deps])
useAnim* hook creates whole animation, but useInit* and usePath* hooks can be used to only create point or path definition Almost all of animation variants have both useAnim, usePath and useInit variants
// does not request whole anim definition in links, see later
useAnimChain([
useAnimLine({
init: useInputConstant({
state: 0
}),
config: useInputDynamicSet({
target: 100,
velocity: 1e-2,
effect: state => {
console.log("Animation Tick: ", state)
}
})
}),
// only defining path
usePathLine(useInputDynamicSet({
target: 100,
velocity: 1e-2,
effect: state => {
console.log("Animation Tick: ", state)
}
}))
] as const)
Linear animation
const App = () => {
const [target, target_set] = useState(100)
useRunAnimInterval({
scheduler: scheduler_raf,
src: useAnimLine({
init: useInputConstant({
state: 0
}),
config: useInputDynamicSet({
target: target,
velocity: 1e-1,
effect: state => {
console.log("Animation 1: ", state)
}
})
})
})
return <button onClick={ () => { target_set(target_old => target_old + 100) } }>
Increase target {target}
</button>
}
Spring-like animation
const App = () => {
const [target, target_set] = useState(100)
useRunAnimInterval({
scheduler: scheduler_raf,
src: useAnimSpring({
init: useInputConstant({
state: 0,
velocity: -100,
}),
config: useInputDynamicSet({
target: target,
// bigger faster
natfreq: 1e-3,
// dampratio < 1 - will overshoot, >= 1 will not overshoot, dampratio <= 0 - inifinite animation
dampratio: 0.1,
// will forcefully finish animation when it's too slow and close to target
precision: {
velocity: 1e-3,
displacement: 1e-4,
},
effect: state => {
console.log("Animation 1: ", state)
}
})
})
})
return <button onClick={ () => { target_set(target_old => target_old + 100) } }>
Increase target {target}
</button>
}
Speed up or slow down animation
const App = () => {
const [target, target_set] = useState(100)
useRunAnimInterval({
scheduler: scheduler_raf,
src: useAnimPlayback({
config: useInputDynamicSet({
multiplire: 2.5
}),
src: useAnimSpring({
init: useInputConstant({
state: 0,
velocity: -100,
}),
config: useInputDynamicSet({
target: target,
natfreq: 1e-3,
dampratio: 0.1,
effect: state => {
console.log("Animation 1: ", state)
}
})
})
})
})
return <button onClick={ () => { target_set(target_old => target_old + 100) } }>
Increase target {target}
</button>
}
Emit animations in sequence, if animation completed once, when target updated it will emit in parallel
const App = () => {
const [target, target_set] = useState(100)
useRunAnimInterval({
scheduler: scheduler_raf,
src: useAnimSequence([
useAnimLine({
init: useInputConstant({
state: 0
}),
config: useInputDynamicSet({
target: target,
velocity: 1e-1,
effect: state => {
console.log("Animation 1: ", state)
}
})
}),
useAnimLine({
init: useInputConstant({
state: 0
}),
config: useInputDynamicSet({
target: target * 2,
velocity: 1e-1,
effect: state => {
console.log("Animation 2: ", state)
}
})
})
] as const)
})
return <button onClick={ () => { target_set(target_old => target_old + 100) } }>
Increase target {target}
</button>
}
Init animations in sequence, but only emit one at a time event if it has finished before
const App = () => {
const [target, target_set] = useState(100)
useRunAnimInterval({
scheduler: scheduler_raf,
src: useAnimSequenceStrict([
useAnimLine({
init: useInputConstant({
state: 0
}),
config: useInputDynamicSet({
target: target,
velocity: 1e-1,
effect: state => {
console.log("Animation 1: ", state)
}
})
}),
useAnimLine({
init: useInputConstant({
state: 0
}),
config: useInputDynamicSet({
target: target * 2,
velocity: 1e-1,
effect: state => {
console.log("Animation 2: ", state)
}
})
})
] as const)
})
return <button onClick={ () => { target_set(target_old => target_old + 100) } }>
Increase target {target}
</button>
}
Init animations in parallel
const App = () => {
const [target, target_set] = useState(100)
useRunAnimInterval({
scheduler: scheduler_raf,
src: useAnimMerge([
useAnimLine({
init: useInputConstant({
state: 0
}),
config: useInputDynamicSet({
target: target,
velocity: 1e-1,
effect: state => {
console.log("Animation 1: ", state)
}
})
}),
useAnimLine({
init: useInputConstant({
state: 0
}),
config: useInputDynamicSet({
target: target * 2,
velocity: 1e-1,
effect: state => {
console.log("Animation 2: ", state)
}
})
})
] as const)
})
return <button onClick={ () => { target_set(target_old => target_old + 100) } }>
Increase target {target}
</button>
}
Emit animations in sequence, but with shared point
const App = () => {
const [target, target_set] = useState(100)
// first element should be animation definition
// chain links share point so no need to define init futher
useRunAnimInterval({
scheduler: scheduler_raf,
src: useAnimChain([
useAnimLine({
init: useInputConstant({
state: 0
}),
config: useInputDynamicSet({
target: target,
velocity: 1e-1,
effect: state => {
console.log("Animation 1: ", state)
}
})
}),
usePathLine(useInputDynamicSet({
target: target * 2,
velocity: 1e-1,
effect: state => {
console.log("Animation 2: ", state)
}
}))
] as const)
})
return <button onClick={ () => { target_set(target_old => target_old + 100) } }>
Increase target {target}
</button>
}
Like chain but with threads
const App = () => {
const [target, target_set] = useState(100)
// First element of each thread should be animation definition
// Thread share point, not need to define init futher
useRunAnimInterval({
scheduler: scheduler_raf,
src: useAnimChainMap([
{
thread_a: useAnimLine({
init: useInputConstant({
state: 0
}),
config: useInputDynamicSet({
target: target,
velocity: 1e-1,
effect: state => {
console.log("Animation 1a: ", state)
}
})
})
},
{
thread_a: usePathLine({
init: useInputConstant({
state: 0
}),
config: useInputDynamicSet({
target: target * 2,
velocity: 1e-1,
effect: state => {
console.log("Animation 2a: ", state)
}
})
}),
thread_b: useAnimLine({
init: useInputConstant({
state: 0
}),
config: useInputDynamicSet({
target: target,
velocity: 1e-1,
effect: state => {
console.log("Animation 1b: ", state)
}
})
})
}
] as const)
})
return <button onClick={ () => { target_set(target_old => target_old + 100) } }>
Increase target {target}
</button>
}
Repeat an animation
const App = () => {
const [target, target_set] = useState(100)
useRunAnimInterval({
scheduler: scheduler_raf,
src: useAnimLoop({
src: useAnimLine({
init: useInputConstant({
state: 0
}),
config: useInputDynamicSet({
target: target,
velocity: 1e-1,
effect: state => {
console.log("Animation 1a: ", state)
}
})
}),
init: useInputConstant({
// will make it first time and then repeat 3 times
repeat: 3
})
})
})
return <button onClick={ () => { target_set(target_old => target_old + 100) } }>
Increase target {target}
</button>
}
const App = () => {
const [target, target_set] = useState(100)
useRunAnimInterval({
scheduler: scheduler_raf,
src: useAnim(
useInitLine(useInputConstant({
state: 0
})),
usePathLine(useInputDynamicSet({
target: target,
velocity: 1e-1,
effect: state => {
console.log("Animation 1a: ", state)
}
})
),
})
return <button onClick={ () => { target_set(target_old => target_old + 100) } }>
Increase target {target}
</button>
}
Adapt animation for different kind of point
const App = () => {
const [target, target_set] = useState(100)
// first element should be animation definition
useRunAnimInterval({
scheduler: scheduler_raf,
src: useAnimChain([
useAnimPipe({
src: useAnimLine({
init: useInputConstant({
state: 0
}),
config: useInputDynamicSet({
target: target,
velocity: 1e-1,
effect: state => {
console.log("Animation 1: ", state)
}
})
}),
pipei: (point_input: AnimSpring_Point): AnimLine_Point => ({
state: point_input.state
}),
pipeo: (point_input: AnimLine_Point): AnimSpring_Point => ({
state: point_input.state,
velocity: 1e-1
}),
}),
usePathSpring(useInputDynamicSet({
natfreq: 1e-2,
dampratio: 0.1,
target: target * 2,
effect: state => {
console.log("Animation 2: ", state)
}
}))
] as const)
})
return <button onClick={ () => { target_set(target_old => target_old + 100) } }>
Increase target {target}
</button>
}
Makes animation monolith, when one updates initial conditions - restarts the whole thing
const App = () => {
const [target, target_set] = useState(100)
useRunAnimInterval({
scheduler: scheduler_raf,
src: useAnimCluster(useAnimMerge([
useAnimLine({
init: useInputConstant({
state: 0
}),
config: useInputDynamicSet({
target: target,
velocity: 1e-1,
effect: state => {
console.log("Animation 1: ", state)
}
})
}),
useAnimLine({
init: useInputConstant({
state: 0
}),
config: useInputDynamicSet({
target: target * 2,
velocity: 1e-1,
effect: state => {
console.log("Animation 2: ", state)
}
})
})
] as const))
})
return <button onClick={ () => { target_set(target_old => target_old + 100) } }>
Increase target {target}
</button>
}
Animate ref's styles with springs
const App = () => {
const [natfreq, natfreq_set] = useState(1e-2)
const [width_target, width_target_set] = useState(500)
const ref_element = useRef<HTMLDivElement | null>(null)
// run animation with animation frames
useRunAnimInterval({
scheduler: scheduler_raf,
// will treat child animations individually as much as posiible
// that means when one of children changes it's initial value it will restart without affecting unrelated animations
// if false (by default) - runner will treat animation as monolith
spread: true,
src: useAnimStyleMapSpring({
// target element
ref: useRefObject(ref_element),
// default config for animations
config: useInputDynamicSet({
natfreq,
dampratio: 0.1,
}),
// useInputDynamicSet means
properties: useInputDynamicSet({
height: transvalue_new_cssunit({ from: 0, target: 400, unit: "px" }),
// when widht_target updates - this animation will also update
width: transvalue_new_cssunit({ from: 0, target: width_target, unit: "px" }),
// color animation
// property names are not transformed = need to preserve dashes
"background-color": transvalue_new_csscolor([[0, 200], [0, 150], [0, 255], [120, 255]]),
transform: transvalue_new_csstransform({
// specific config for property
scaleX: transvalue_new_cssnumber({
from: 1,
target: {
target: 1.6,
natfreq: 5e-3,
precision: {
velocity: 1e-4,
displacement: 1e-5
}
},
})
})
})
}),
})
return <>
<button onClick={() => { natfreq_set(natfreq_old => natfreq_old * 2) } }>
Increase natfreq {natfreq}
</button>
<button onClick={() => { width_target_set(width_target_old => width_target_old + 500) } }>
Increase width_target {width_target}
</button>
<div ref={ref_element} />
</>
}
Animate styles of target with line
const App = () => {
const [velocity, velocity_set] = useState(1e-2)
const [width_target, width_target_set] = useState(500)
const ref_element = useRef<HTMLDivElement | null>(null)
// run animation with animation frames
useRunAnimInterval({
scheduler: scheduler_raf,
// will treat child animations individually as much as posiible
// that means when one of children changes it's initial value it will restart without affecting unrelated animations
// if false (by default) - runner will treat animation as monolith
spread: true,
src: useAnimStyleMapLine({
// target element
ref: useRefObject(ref_element),
// default config for animations
config: useInputDynamicSet({
velocity
}),
// useInputDynamicSet means
properties: useInputDynamicSet({
height: transvalue_new_cssunit({ from: 0, target: 400, unit: "px" }),
// when widht_target updates - this animation will also update
width: transvalue_new_cssunit({ from: 0, target: width_target, unit: "px" }),
// color animation
// property names are not transformed = need to preserve dashes
"background-color": transvalue_new_csscolor([[0, 200], [0, 150], [0, 255], [120, 255]]),
transform: transvalue_new_csstransform({
// specific config for property
scaleX: transvalue_new_cssnumber({
from: 1,
target: {
target: 1.6,
velocity: 1e-4
},
})
})
})
}),
})
return <>
<button onClick={() => { velocity_set(velocity_old => velocity_old * 2) } }>
Increase velocity {velocity}
</button>
<button onClick={() => { width_target_set(width_target_old => width_target_old + 500) } }>
Increase width_target {width_target}
</button>
<div ref={ref_element} />
</>
}
FAQs
Declarative animations for react
We found that @qyu/anim-react demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.