| 185 | setFrame((f) => f + 1); |
| 186 | |
| 187 | const step = () => { |
| 188 | const frameStart = performance.now(); |
| 189 | let settled = false; |
| 190 | do { |
| 191 | sim.tick(); |
| 192 | ticks += 1; |
| 193 | if (sim.alpha() < SETTLE_ALPHA_MIN) { |
| 194 | settled = true; |
| 195 | break; |
| 196 | } |
| 197 | } while (performance.now() - frameStart < SETTLE_TICK_BUDGET_MS); |
| 198 | |
| 199 | if (settled || performance.now() - startedAt > SETTLE_MAX_MS) { |
| 200 | sim.stop(); |
| 201 | rafRef.current = null; |
| 202 | setProgress(null); |
| 203 | setFrame((f) => f + 1); |
| 204 | return; |
| 205 | } |
| 206 | setProgress(Math.min(0.99, ticks / target)); |
| 207 | setFrame((f) => f + 1); |
| 208 | rafRef.current = requestAnimationFrame(step); |
| 209 | }; |
| 210 | |
| 211 | rafRef.current = requestAnimationFrame(step); |
| 212 | return () => { |