tekiyo-physics 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,1916 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
5
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
6
+ const react = require("react");
7
+ const jsxRuntime = require("react/jsx-runtime");
8
+ class Vector2 {
9
+ constructor(x = 0, y = 0) {
10
+ this.x = x;
11
+ this.y = y;
12
+ }
13
+ static zero() {
14
+ return new Vector2(0, 0);
15
+ }
16
+ static from(x, y) {
17
+ return new Vector2(x, y);
18
+ }
19
+ static fromObject(obj) {
20
+ return new Vector2(obj.x, obj.y);
21
+ }
22
+ add(other) {
23
+ return new Vector2(this.x + other.x, this.y + other.y);
24
+ }
25
+ subtract(other) {
26
+ return new Vector2(this.x - other.x, this.y - other.y);
27
+ }
28
+ multiply(scalar) {
29
+ return new Vector2(this.x * scalar, this.y * scalar);
30
+ }
31
+ divide(scalar) {
32
+ if (scalar === 0) return Vector2.zero();
33
+ return new Vector2(this.x / scalar, this.y / scalar);
34
+ }
35
+ get magnitude() {
36
+ return Math.sqrt(this.x * this.x + this.y * this.y);
37
+ }
38
+ get magnitudeSquared() {
39
+ return this.x * this.x + this.y * this.y;
40
+ }
41
+ normalize() {
42
+ const mag = this.magnitude;
43
+ if (mag === 0) return Vector2.zero();
44
+ return this.divide(mag);
45
+ }
46
+ clamp(maxMagnitude) {
47
+ const mag = this.magnitude;
48
+ if (mag <= maxMagnitude) return this;
49
+ return this.normalize().multiply(maxMagnitude);
50
+ }
51
+ clampComponents(min, max) {
52
+ return new Vector2(
53
+ Math.max(min.x, Math.min(max.x, this.x)),
54
+ Math.max(min.y, Math.min(max.y, this.y))
55
+ );
56
+ }
57
+ lerp(target, t) {
58
+ return new Vector2(
59
+ this.x + (target.x - this.x) * t,
60
+ this.y + (target.y - this.y) * t
61
+ );
62
+ }
63
+ dot(other) {
64
+ return this.x * other.x + this.y * other.y;
65
+ }
66
+ distanceTo(other) {
67
+ return this.subtract(other).magnitude;
68
+ }
69
+ equals(other, epsilon = 1e-4) {
70
+ return Math.abs(this.x - other.x) < epsilon && Math.abs(this.y - other.y) < epsilon;
71
+ }
72
+ isZero(epsilon = 1e-4) {
73
+ return this.magnitude < epsilon;
74
+ }
75
+ negate() {
76
+ return new Vector2(-this.x, -this.y);
77
+ }
78
+ abs() {
79
+ return new Vector2(Math.abs(this.x), Math.abs(this.y));
80
+ }
81
+ toObject() {
82
+ return { x: this.x, y: this.y };
83
+ }
84
+ }
85
+ const DEFAULT_SPRING_CONFIG = {
86
+ tension: 170,
87
+ friction: 26,
88
+ mass: 1,
89
+ precision: 0.01
90
+ };
91
+ class Spring {
92
+ constructor(initialPosition = Vector2.zero(), config = {}) {
93
+ __publicField(this, "position");
94
+ __publicField(this, "velocity");
95
+ __publicField(this, "target");
96
+ __publicField(this, "config");
97
+ this.position = initialPosition;
98
+ this.velocity = Vector2.zero();
99
+ this.target = initialPosition;
100
+ this.config = { ...DEFAULT_SPRING_CONFIG, ...config };
101
+ }
102
+ setTarget(target) {
103
+ this.target = target;
104
+ }
105
+ setPosition(position) {
106
+ this.position = position;
107
+ }
108
+ setVelocity(velocity) {
109
+ this.velocity = velocity;
110
+ }
111
+ updateConfig(config) {
112
+ this.config = { ...this.config, ...config };
113
+ }
114
+ /**
115
+ * Advance the spring simulation by deltaTime seconds
116
+ * Uses semi-implicit Euler for stability
117
+ */
118
+ step(deltaTime) {
119
+ const { tension, friction, mass, precision } = this.config;
120
+ const displacement = this.position.subtract(this.target);
121
+ const springForce = displacement.multiply(-tension);
122
+ const dampingForce = this.velocity.multiply(-friction);
123
+ const totalForce = springForce.add(dampingForce);
124
+ const acceleration = totalForce.divide(mass);
125
+ this.velocity = this.velocity.add(acceleration.multiply(deltaTime));
126
+ this.position = this.position.add(this.velocity.multiply(deltaTime));
127
+ const isSettled = displacement.magnitude < precision && this.velocity.magnitude < precision;
128
+ if (isSettled) {
129
+ this.position = this.target;
130
+ this.velocity = Vector2.zero();
131
+ }
132
+ return {
133
+ position: this.position,
134
+ velocity: this.velocity,
135
+ target: this.target,
136
+ isSettled
137
+ };
138
+ }
139
+ getState() {
140
+ const displacement = this.position.subtract(this.target);
141
+ return {
142
+ position: this.position,
143
+ velocity: this.velocity,
144
+ target: this.target,
145
+ isSettled: displacement.magnitude < this.config.precision && this.velocity.magnitude < this.config.precision
146
+ };
147
+ }
148
+ /**
149
+ * Immediately snap to target
150
+ */
151
+ snapToTarget() {
152
+ this.position = this.target;
153
+ this.velocity = Vector2.zero();
154
+ }
155
+ }
156
+ class Spring1D {
157
+ constructor(initialValue = 0, config = {}) {
158
+ __publicField(this, "position");
159
+ __publicField(this, "velocity");
160
+ __publicField(this, "target");
161
+ __publicField(this, "config");
162
+ this.position = initialValue;
163
+ this.velocity = 0;
164
+ this.target = initialValue;
165
+ this.config = { ...DEFAULT_SPRING_CONFIG, ...config };
166
+ }
167
+ setTarget(target) {
168
+ this.target = target;
169
+ }
170
+ setPosition(position) {
171
+ this.position = position;
172
+ }
173
+ setVelocity(velocity) {
174
+ this.velocity = velocity;
175
+ }
176
+ step(deltaTime) {
177
+ const { tension, friction, mass, precision } = this.config;
178
+ const displacement = this.position - this.target;
179
+ const springForce = -tension * displacement;
180
+ const dampingForce = -friction * this.velocity;
181
+ const acceleration = (springForce + dampingForce) / mass;
182
+ this.velocity += acceleration * deltaTime;
183
+ this.position += this.velocity * deltaTime;
184
+ const isSettled = Math.abs(displacement) < precision && Math.abs(this.velocity) < precision;
185
+ if (isSettled) {
186
+ this.position = this.target;
187
+ this.velocity = 0;
188
+ }
189
+ return {
190
+ value: this.position,
191
+ velocity: this.velocity,
192
+ isSettled
193
+ };
194
+ }
195
+ getValue() {
196
+ return this.position;
197
+ }
198
+ snapToTarget() {
199
+ this.position = this.target;
200
+ this.velocity = 0;
201
+ }
202
+ }
203
+ class VelocityTracker {
204
+ constructor(maxSamples = 8, maxAge = 100) {
205
+ __publicField(this, "samples", []);
206
+ __publicField(this, "maxSamples");
207
+ __publicField(this, "maxAge");
208
+ this.maxSamples = maxSamples;
209
+ this.maxAge = maxAge;
210
+ }
211
+ /**
212
+ * Record a position sample
213
+ */
214
+ addSample(position, timestamp = performance.now()) {
215
+ this.samples.push({ position, timestamp });
216
+ if (this.samples.length > this.maxSamples) {
217
+ this.samples.shift();
218
+ }
219
+ }
220
+ /**
221
+ * Calculate current velocity from sample history
222
+ * Returns smoothed velocity vector in pixels per second
223
+ */
224
+ getVelocity() {
225
+ const now = performance.now();
226
+ this.samples = this.samples.filter(
227
+ (sample) => now - sample.timestamp < this.maxAge
228
+ );
229
+ if (this.samples.length < 2) {
230
+ return Vector2.zero();
231
+ }
232
+ let totalWeight = 0;
233
+ let weightedVelocity = Vector2.zero();
234
+ for (let i = 1; i < this.samples.length; i++) {
235
+ const prev = this.samples[i - 1];
236
+ const curr = this.samples[i];
237
+ const dt = (curr.timestamp - prev.timestamp) / 1e3;
238
+ if (dt <= 0) continue;
239
+ const instantVelocity = curr.position.subtract(prev.position).divide(dt);
240
+ const age = now - curr.timestamp;
241
+ const weight = Math.exp(-age / this.maxAge);
242
+ weightedVelocity = weightedVelocity.add(instantVelocity.multiply(weight));
243
+ totalWeight += weight;
244
+ }
245
+ if (totalWeight === 0) {
246
+ return Vector2.zero();
247
+ }
248
+ return weightedVelocity.divide(totalWeight);
249
+ }
250
+ /**
251
+ * Get velocity magnitude in pixels per second
252
+ */
253
+ getSpeed() {
254
+ return this.getVelocity().magnitude;
255
+ }
256
+ /**
257
+ * Check if current velocity qualifies as a flick gesture
258
+ */
259
+ isFlick(threshold = 500) {
260
+ return this.getSpeed() > threshold;
261
+ }
262
+ /**
263
+ * Get dominant direction of movement
264
+ */
265
+ getDirection() {
266
+ const velocity = this.getVelocity();
267
+ const speed = velocity.magnitude;
268
+ if (speed < 10) return "none";
269
+ if (Math.abs(velocity.x) > Math.abs(velocity.y)) {
270
+ return velocity.x > 0 ? "right" : "left";
271
+ } else {
272
+ return velocity.y > 0 ? "down" : "up";
273
+ }
274
+ }
275
+ /**
276
+ * Clear all samples
277
+ */
278
+ reset() {
279
+ this.samples = [];
280
+ }
281
+ /**
282
+ * Get the last recorded position
283
+ */
284
+ getLastPosition() {
285
+ if (this.samples.length === 0) return null;
286
+ return this.samples[this.samples.length - 1].position;
287
+ }
288
+ }
289
+ class VelocityTracker1D {
290
+ constructor(maxSamples = 8, maxAge = 100) {
291
+ __publicField(this, "samples", []);
292
+ __publicField(this, "maxSamples");
293
+ __publicField(this, "maxAge");
294
+ this.maxSamples = maxSamples;
295
+ this.maxAge = maxAge;
296
+ }
297
+ addSample(value, timestamp = performance.now()) {
298
+ this.samples.push({ value, timestamp });
299
+ if (this.samples.length > this.maxSamples) {
300
+ this.samples.shift();
301
+ }
302
+ }
303
+ getVelocity() {
304
+ const now = performance.now();
305
+ this.samples = this.samples.filter((s) => now - s.timestamp < this.maxAge);
306
+ if (this.samples.length < 2) return 0;
307
+ let totalWeight = 0;
308
+ let weightedVelocity = 0;
309
+ for (let i = 1; i < this.samples.length; i++) {
310
+ const prev = this.samples[i - 1];
311
+ const curr = this.samples[i];
312
+ const dt = (curr.timestamp - prev.timestamp) / 1e3;
313
+ if (dt <= 0) continue;
314
+ const instantVelocity = (curr.value - prev.value) / dt;
315
+ const age = now - curr.timestamp;
316
+ const weight = Math.exp(-age / this.maxAge);
317
+ weightedVelocity += instantVelocity * weight;
318
+ totalWeight += weight;
319
+ }
320
+ return totalWeight > 0 ? weightedVelocity / totalWeight : 0;
321
+ }
322
+ reset() {
323
+ this.samples = [];
324
+ }
325
+ }
326
+ const DEFAULT_FRICTION_CONFIG = {
327
+ decay: 0.95,
328
+ stopThreshold: 0.1,
329
+ maxVelocity: 2e3
330
+ };
331
+ class Momentum {
332
+ constructor(initialPosition = Vector2.zero(), config = {}) {
333
+ __publicField(this, "position");
334
+ __publicField(this, "velocity");
335
+ __publicField(this, "config");
336
+ __publicField(this, "isActive", false);
337
+ this.position = initialPosition;
338
+ this.velocity = Vector2.zero();
339
+ this.config = { ...DEFAULT_FRICTION_CONFIG, ...config };
340
+ }
341
+ /**
342
+ * Start momentum with initial velocity
343
+ */
344
+ start(position, velocity) {
345
+ this.position = position;
346
+ this.velocity = velocity.clamp(this.config.maxVelocity);
347
+ this.isActive = true;
348
+ }
349
+ /**
350
+ * Stop momentum immediately
351
+ */
352
+ stop() {
353
+ this.velocity = Vector2.zero();
354
+ this.isActive = false;
355
+ }
356
+ /**
357
+ * Update momentum simulation
358
+ * @param deltaTime Time in seconds
359
+ */
360
+ step(deltaTime) {
361
+ if (!this.isActive) {
362
+ return {
363
+ position: this.position,
364
+ velocity: Vector2.zero(),
365
+ isActive: false
366
+ };
367
+ }
368
+ this.position = this.position.add(this.velocity.multiply(deltaTime));
369
+ const frameDecay = Math.pow(this.config.decay, deltaTime * 60);
370
+ this.velocity = this.velocity.multiply(frameDecay);
371
+ if (this.velocity.magnitude < this.config.stopThreshold) {
372
+ this.velocity = Vector2.zero();
373
+ this.isActive = false;
374
+ }
375
+ return {
376
+ position: this.position,
377
+ velocity: this.velocity,
378
+ isActive: this.isActive
379
+ };
380
+ }
381
+ /**
382
+ * Apply rubber band effect at boundaries
383
+ */
384
+ applyRubberBand(bounds, rubberBandFactor = 0.55) {
385
+ let newX = this.position.x;
386
+ let newY = this.position.y;
387
+ if (this.position.x < bounds.min.x) {
388
+ const overshoot = bounds.min.x - this.position.x;
389
+ newX = bounds.min.x - overshoot * rubberBandFactor;
390
+ } else if (this.position.x > bounds.max.x) {
391
+ const overshoot = this.position.x - bounds.max.x;
392
+ newX = bounds.max.x + overshoot * rubberBandFactor;
393
+ }
394
+ if (this.position.y < bounds.min.y) {
395
+ const overshoot = bounds.min.y - this.position.y;
396
+ newY = bounds.min.y - overshoot * rubberBandFactor;
397
+ } else if (this.position.y > bounds.max.y) {
398
+ const overshoot = this.position.y - bounds.max.y;
399
+ newY = bounds.max.y + overshoot * rubberBandFactor;
400
+ }
401
+ this.position = new Vector2(newX, newY);
402
+ }
403
+ getPosition() {
404
+ return this.position;
405
+ }
406
+ getVelocity() {
407
+ return this.velocity;
408
+ }
409
+ getIsActive() {
410
+ return this.isActive;
411
+ }
412
+ setPosition(position) {
413
+ this.position = position;
414
+ }
415
+ updateConfig(config) {
416
+ this.config = { ...this.config, ...config };
417
+ }
418
+ }
419
+ class Momentum1D {
420
+ constructor(initialPosition = 0, config = {}) {
421
+ __publicField(this, "position");
422
+ __publicField(this, "velocity");
423
+ __publicField(this, "config");
424
+ __publicField(this, "isActive", false);
425
+ this.position = initialPosition;
426
+ this.velocity = 0;
427
+ this.config = { ...DEFAULT_FRICTION_CONFIG, ...config };
428
+ }
429
+ start(position, velocity) {
430
+ this.position = position;
431
+ this.velocity = Math.sign(velocity) * Math.min(Math.abs(velocity), this.config.maxVelocity);
432
+ this.isActive = true;
433
+ }
434
+ stop() {
435
+ this.velocity = 0;
436
+ this.isActive = false;
437
+ }
438
+ step(deltaTime) {
439
+ if (!this.isActive) {
440
+ return { position: this.position, velocity: 0, isActive: false };
441
+ }
442
+ this.position += this.velocity * deltaTime;
443
+ const frameDecay = Math.pow(this.config.decay, deltaTime * 60);
444
+ this.velocity *= frameDecay;
445
+ if (Math.abs(this.velocity) < this.config.stopThreshold) {
446
+ this.velocity = 0;
447
+ this.isActive = false;
448
+ }
449
+ return {
450
+ position: this.position,
451
+ velocity: this.velocity,
452
+ isActive: this.isActive
453
+ };
454
+ }
455
+ getPosition() {
456
+ return this.position;
457
+ }
458
+ setPosition(position) {
459
+ this.position = position;
460
+ }
461
+ }
462
+ class PhysicsEngineCore {
463
+ constructor() {
464
+ __publicField(this, "bodies", /* @__PURE__ */ new Map());
465
+ __publicField(this, "rafId", null);
466
+ __publicField(this, "lastTime", 0);
467
+ __publicField(this, "isRunning", false);
468
+ // Cap deltaTime to prevent spiral of death (max ~30fps frame time)
469
+ __publicField(this, "maxDelta", 1 / 30);
470
+ /**
471
+ * Main RAF loop
472
+ */
473
+ __publicField(this, "loop", () => {
474
+ if (!this.isRunning) return;
475
+ const currentTime = performance.now();
476
+ let deltaTime = (currentTime - this.lastTime) / 1e3;
477
+ this.lastTime = currentTime;
478
+ deltaTime = Math.min(deltaTime, this.maxDelta);
479
+ const sortedBodies = Array.from(this.bodies.values()).sort(
480
+ (a, b) => b.priority - a.priority
481
+ );
482
+ for (const body of sortedBodies) {
483
+ body.update(deltaTime);
484
+ }
485
+ this.rafId = requestAnimationFrame(this.loop);
486
+ });
487
+ }
488
+ /**
489
+ * Register a physics body to receive updates
490
+ */
491
+ register(id, update, priority = 0) {
492
+ this.bodies.set(id, { id, update, priority });
493
+ this.start();
494
+ }
495
+ /**
496
+ * Unregister a physics body
497
+ */
498
+ unregister(id) {
499
+ this.bodies.delete(id);
500
+ if (this.bodies.size === 0) {
501
+ this.stop();
502
+ }
503
+ }
504
+ /**
505
+ * Check if a body is registered
506
+ */
507
+ has(id) {
508
+ return this.bodies.has(id);
509
+ }
510
+ /**
511
+ * Start the physics loop
512
+ */
513
+ start() {
514
+ if (this.isRunning) return;
515
+ this.isRunning = true;
516
+ this.lastTime = performance.now();
517
+ this.loop();
518
+ }
519
+ /**
520
+ * Stop the physics loop
521
+ */
522
+ stop() {
523
+ if (!this.isRunning) return;
524
+ this.isRunning = false;
525
+ if (this.rafId !== null) {
526
+ cancelAnimationFrame(this.rafId);
527
+ this.rafId = null;
528
+ }
529
+ }
530
+ /**
531
+ * Get current number of active bodies
532
+ */
533
+ getActiveCount() {
534
+ return this.bodies.size;
535
+ }
536
+ /**
537
+ * Check if engine is running
538
+ */
539
+ getIsRunning() {
540
+ return this.isRunning;
541
+ }
542
+ }
543
+ const PhysicsEngine = new PhysicsEngineCore();
544
+ let idCounter = 0;
545
+ function generatePhysicsId(prefix = "physics") {
546
+ return `${prefix}_${++idCounter}_${Date.now().toString(36)}`;
547
+ }
548
+ const ios = {
549
+ name: "ios",
550
+ description: "iOS-like smooth, natural feel",
551
+ spring: {
552
+ tension: 170,
553
+ friction: 26,
554
+ mass: 1,
555
+ precision: 0.01
556
+ },
557
+ friction: {
558
+ decay: 0.95,
559
+ stopThreshold: 0.1,
560
+ maxVelocity: 2e3
561
+ },
562
+ stretch: {
563
+ intensity: 0.08,
564
+ maxVelocity: 1500
565
+ },
566
+ lift: {
567
+ scale: 1.02,
568
+ shadowIntensity: 0.8
569
+ }
570
+ };
571
+ const snappy = {
572
+ name: "snappy",
573
+ description: "Ultra-responsive, instant feedback",
574
+ spring: {
575
+ tension: 400,
576
+ friction: 30,
577
+ mass: 0.8,
578
+ precision: 0.01
579
+ },
580
+ friction: {
581
+ decay: 0.92,
582
+ stopThreshold: 0.5,
583
+ maxVelocity: 3e3
584
+ },
585
+ stretch: {
586
+ intensity: 0.06,
587
+ maxVelocity: 2e3
588
+ },
589
+ lift: {
590
+ scale: 1.015,
591
+ shadowIntensity: 0.6
592
+ }
593
+ };
594
+ const smooth = {
595
+ name: "smooth",
596
+ description: "Slow, luxurious, elegant motion",
597
+ spring: {
598
+ tension: 120,
599
+ friction: 20,
600
+ mass: 1.5,
601
+ precision: 5e-3
602
+ },
603
+ friction: {
604
+ decay: 0.97,
605
+ stopThreshold: 0.05,
606
+ maxVelocity: 1500
607
+ },
608
+ stretch: {
609
+ intensity: 0.1,
610
+ maxVelocity: 1200
611
+ },
612
+ lift: {
613
+ scale: 1.04,
614
+ shadowIntensity: 1.2
615
+ }
616
+ };
617
+ const stiff = {
618
+ name: "stiff",
619
+ description: "Direct, precise, no overshoot",
620
+ spring: {
621
+ tension: 300,
622
+ friction: 35,
623
+ mass: 1,
624
+ precision: 0.01
625
+ },
626
+ friction: {
627
+ decay: 0.9,
628
+ stopThreshold: 0.2,
629
+ maxVelocity: 2500
630
+ },
631
+ stretch: {
632
+ intensity: 0.04,
633
+ maxVelocity: 2500
634
+ },
635
+ lift: {
636
+ scale: 1.01,
637
+ shadowIntensity: 0.5
638
+ }
639
+ };
640
+ const gentle = {
641
+ name: "gentle",
642
+ description: "Soft, forgiving, approachable",
643
+ spring: {
644
+ tension: 150,
645
+ friction: 22,
646
+ mass: 1.2,
647
+ precision: 0.01
648
+ },
649
+ friction: {
650
+ decay: 0.96,
651
+ stopThreshold: 0.1,
652
+ maxVelocity: 1800
653
+ },
654
+ stretch: {
655
+ intensity: 0.12,
656
+ maxVelocity: 1400
657
+ },
658
+ lift: {
659
+ scale: 1.03,
660
+ shadowIntensity: 1
661
+ }
662
+ };
663
+ const presets = {
664
+ ios,
665
+ snappy,
666
+ smooth,
667
+ stiff,
668
+ gentle
669
+ };
670
+ function getPreset(name) {
671
+ return presets[name];
672
+ }
673
+ function getSpringConfig(preset) {
674
+ var _a;
675
+ if (typeof preset === "string") {
676
+ return ((_a = presets[preset]) == null ? void 0 : _a.spring) ?? ios.spring;
677
+ }
678
+ return preset;
679
+ }
680
+ function getFrictionConfig(preset) {
681
+ var _a;
682
+ if (typeof preset === "string") {
683
+ return ((_a = presets[preset]) == null ? void 0 : _a.friction) ?? ios.friction;
684
+ }
685
+ return preset;
686
+ }
687
+ const defaultContext = {
688
+ spring: DEFAULT_SPRING_CONFIG,
689
+ friction: DEFAULT_FRICTION_CONFIG,
690
+ stretch: {
691
+ intensity: 0.12,
692
+ maxVelocity: 2e3
693
+ },
694
+ lift: {
695
+ scale: 1.03,
696
+ shadowIntensity: 1
697
+ }
698
+ };
699
+ const PhysicsContext = react.createContext(defaultContext);
700
+ function PhysicsProvider({
701
+ children,
702
+ preset = "ios",
703
+ spring,
704
+ friction,
705
+ stretch,
706
+ lift
707
+ }) {
708
+ const value = react.useMemo(() => {
709
+ const basePreset = typeof preset === "string" ? presets[preset] ?? ios : preset;
710
+ return {
711
+ spring: { ...basePreset.spring, ...spring },
712
+ friction: { ...basePreset.friction, ...friction },
713
+ stretch: { ...basePreset.stretch, ...stretch },
714
+ lift: { ...basePreset.lift, ...lift }
715
+ };
716
+ }, [preset, spring, friction, stretch, lift]);
717
+ return /* @__PURE__ */ jsxRuntime.jsx(PhysicsContext.Provider, { value, children });
718
+ }
719
+ function usePhysicsContext() {
720
+ return react.useContext(PhysicsContext);
721
+ }
722
+ function usePhysicsConfig() {
723
+ const context = react.useContext(PhysicsContext);
724
+ return context.spring;
725
+ }
726
+ function useFrictionConfig() {
727
+ const context = react.useContext(PhysicsContext);
728
+ return context.friction;
729
+ }
730
+ function useStretchConfig() {
731
+ const context = react.useContext(PhysicsContext);
732
+ return context.stretch;
733
+ }
734
+ function useLiftConfig() {
735
+ const context = react.useContext(PhysicsContext);
736
+ return context.lift;
737
+ }
738
+ function useSpring(options) {
739
+ const { to, from, config, onRest, immediate = true } = options;
740
+ const globalConfig = usePhysicsConfig();
741
+ const resolvedConfig = react.useMemo(() => {
742
+ if (!config) return { ...DEFAULT_SPRING_CONFIG, ...globalConfig };
743
+ if (typeof config === "string") {
744
+ return { ...DEFAULT_SPRING_CONFIG, ...globalConfig };
745
+ }
746
+ return { ...DEFAULT_SPRING_CONFIG, ...globalConfig, ...config };
747
+ }, [config, globalConfig]);
748
+ const springRef = react.useRef(null);
749
+ const idRef = react.useRef(generatePhysicsId("spring"));
750
+ const onRestRef = react.useRef(onRest);
751
+ onRestRef.current = onRest;
752
+ const [state, setState] = react.useState({
753
+ x: (from == null ? void 0 : from.x) ?? to.x,
754
+ y: (from == null ? void 0 : from.y) ?? to.y,
755
+ isAnimating: false,
756
+ isSettled: true
757
+ });
758
+ react.useEffect(() => {
759
+ const initialPos = from ? Vector2.from(from.x, from.y) : Vector2.from(to.x, to.y);
760
+ springRef.current = new Spring(initialPos, resolvedConfig);
761
+ if (immediate) {
762
+ springRef.current.setTarget(Vector2.from(to.x, to.y));
763
+ }
764
+ return () => {
765
+ PhysicsEngine.unregister(idRef.current);
766
+ };
767
+ }, []);
768
+ react.useEffect(() => {
769
+ if (springRef.current && immediate) {
770
+ springRef.current.setTarget(Vector2.from(to.x, to.y));
771
+ if (!PhysicsEngine.has(idRef.current)) {
772
+ PhysicsEngine.register(idRef.current, (deltaTime) => {
773
+ var _a;
774
+ if (!springRef.current) return;
775
+ const result = springRef.current.step(deltaTime);
776
+ setState({
777
+ x: result.position.x,
778
+ y: result.position.y,
779
+ isAnimating: !result.isSettled,
780
+ isSettled: result.isSettled
781
+ });
782
+ if (result.isSettled) {
783
+ PhysicsEngine.unregister(idRef.current);
784
+ (_a = onRestRef.current) == null ? void 0 : _a.call(onRestRef);
785
+ }
786
+ });
787
+ }
788
+ }
789
+ }, [to.x, to.y, immediate]);
790
+ react.useEffect(() => {
791
+ var _a;
792
+ (_a = springRef.current) == null ? void 0 : _a.updateConfig(resolvedConfig);
793
+ }, [resolvedConfig]);
794
+ const setTarget = react.useCallback((target) => {
795
+ if (!springRef.current) return;
796
+ springRef.current.setTarget(Vector2.from(target.x, target.y));
797
+ if (!PhysicsEngine.has(idRef.current)) {
798
+ PhysicsEngine.register(idRef.current, (deltaTime) => {
799
+ var _a;
800
+ if (!springRef.current) return;
801
+ const result = springRef.current.step(deltaTime);
802
+ setState({
803
+ x: result.position.x,
804
+ y: result.position.y,
805
+ isAnimating: !result.isSettled,
806
+ isSettled: result.isSettled
807
+ });
808
+ if (result.isSettled) {
809
+ PhysicsEngine.unregister(idRef.current);
810
+ (_a = onRestRef.current) == null ? void 0 : _a.call(onRestRef);
811
+ }
812
+ });
813
+ }
814
+ }, []);
815
+ const snapTo = react.useCallback((position) => {
816
+ if (!springRef.current) return;
817
+ springRef.current.setPosition(Vector2.from(position.x, position.y));
818
+ springRef.current.setTarget(Vector2.from(position.x, position.y));
819
+ springRef.current.snapToTarget();
820
+ setState({
821
+ x: position.x,
822
+ y: position.y,
823
+ isAnimating: false,
824
+ isSettled: true
825
+ });
826
+ PhysicsEngine.unregister(idRef.current);
827
+ }, []);
828
+ const impulse = react.useCallback((velocity) => {
829
+ if (!springRef.current) return;
830
+ const currentState = springRef.current.getState();
831
+ springRef.current.setVelocity(
832
+ currentState.velocity.add(Vector2.from(velocity.x, velocity.y))
833
+ );
834
+ if (!PhysicsEngine.has(idRef.current)) {
835
+ PhysicsEngine.register(idRef.current, (deltaTime) => {
836
+ var _a;
837
+ if (!springRef.current) return;
838
+ const result = springRef.current.step(deltaTime);
839
+ setState({
840
+ x: result.position.x,
841
+ y: result.position.y,
842
+ isAnimating: !result.isSettled,
843
+ isSettled: result.isSettled
844
+ });
845
+ if (result.isSettled) {
846
+ PhysicsEngine.unregister(idRef.current);
847
+ (_a = onRestRef.current) == null ? void 0 : _a.call(onRestRef);
848
+ }
849
+ });
850
+ }
851
+ }, []);
852
+ const style = react.useMemo(
853
+ () => ({
854
+ transform: `translate3d(${state.x}px, ${state.y}px, 0)`,
855
+ willChange: state.isAnimating ? "transform" : "auto"
856
+ }),
857
+ [state.x, state.y, state.isAnimating]
858
+ );
859
+ return {
860
+ x: state.x,
861
+ y: state.y,
862
+ style,
863
+ isAnimating: state.isAnimating,
864
+ isSettled: state.isSettled,
865
+ setTarget,
866
+ snapTo,
867
+ impulse
868
+ };
869
+ }
870
+ function useSpring1D(options) {
871
+ const { to, from, config, onRest, immediate = true } = options;
872
+ const globalConfig = usePhysicsConfig();
873
+ const resolvedConfig = react.useMemo(
874
+ () => ({ ...DEFAULT_SPRING_CONFIG, ...globalConfig, ...config }),
875
+ [config, globalConfig]
876
+ );
877
+ const springRef = react.useRef(null);
878
+ const idRef = react.useRef(generatePhysicsId("spring1d"));
879
+ const onRestRef = react.useRef(onRest);
880
+ onRestRef.current = onRest;
881
+ const [state, setState] = react.useState({
882
+ value: from ?? to,
883
+ isAnimating: false,
884
+ isSettled: true
885
+ });
886
+ react.useEffect(() => {
887
+ springRef.current = new Spring1D(from ?? to, resolvedConfig);
888
+ if (immediate) {
889
+ springRef.current.setTarget(to);
890
+ }
891
+ return () => {
892
+ PhysicsEngine.unregister(idRef.current);
893
+ };
894
+ }, []);
895
+ react.useEffect(() => {
896
+ if (springRef.current && immediate) {
897
+ springRef.current.setTarget(to);
898
+ if (!PhysicsEngine.has(idRef.current)) {
899
+ PhysicsEngine.register(idRef.current, (deltaTime) => {
900
+ var _a;
901
+ if (!springRef.current) return;
902
+ const result = springRef.current.step(deltaTime);
903
+ setState({
904
+ value: result.value,
905
+ isAnimating: !result.isSettled,
906
+ isSettled: result.isSettled
907
+ });
908
+ if (result.isSettled) {
909
+ PhysicsEngine.unregister(idRef.current);
910
+ (_a = onRestRef.current) == null ? void 0 : _a.call(onRestRef);
911
+ }
912
+ });
913
+ }
914
+ }
915
+ }, [to, immediate]);
916
+ const setTarget = react.useCallback((target) => {
917
+ if (!springRef.current) return;
918
+ springRef.current.setTarget(target);
919
+ if (!PhysicsEngine.has(idRef.current)) {
920
+ PhysicsEngine.register(idRef.current, (deltaTime) => {
921
+ var _a;
922
+ if (!springRef.current) return;
923
+ const result = springRef.current.step(deltaTime);
924
+ setState({
925
+ value: result.value,
926
+ isAnimating: !result.isSettled,
927
+ isSettled: result.isSettled
928
+ });
929
+ if (result.isSettled) {
930
+ PhysicsEngine.unregister(idRef.current);
931
+ (_a = onRestRef.current) == null ? void 0 : _a.call(onRestRef);
932
+ }
933
+ });
934
+ }
935
+ }, []);
936
+ return {
937
+ value: state.value,
938
+ isAnimating: state.isAnimating,
939
+ isSettled: state.isSettled,
940
+ setTarget
941
+ };
942
+ }
943
+ function useGesture(options) {
944
+ const {
945
+ onDragStart,
946
+ onDrag,
947
+ onDragEnd,
948
+ onFlick,
949
+ onHover,
950
+ onFocus,
951
+ threshold = 3,
952
+ flickThreshold = 500,
953
+ preventTouch = true
954
+ } = options;
955
+ const velocityTracker = react.useRef(new VelocityTracker());
956
+ const startPosition = react.useRef(Vector2.zero());
957
+ const lastPosition = react.useRef(Vector2.zero());
958
+ const isDragging = react.useRef(false);
959
+ const hasExceededThreshold = react.useRef(false);
960
+ const pointerId = react.useRef(null);
961
+ const elementRef = react.useRef(null);
962
+ const handlersRef = react.useRef({ onDragStart, onDrag, onDragEnd, onFlick });
963
+ handlersRef.current = { onDragStart, onDrag, onDragEnd, onFlick };
964
+ const createGestureState = react.useCallback(
965
+ (event, first, last) => {
966
+ const position = Vector2.from(event.clientX, event.clientY);
967
+ const delta = position.subtract(lastPosition.current);
968
+ const offset = position.subtract(startPosition.current);
969
+ const velocity = velocityTracker.current.getVelocity();
970
+ const direction = velocityTracker.current.getDirection();
971
+ return {
972
+ position,
973
+ delta,
974
+ offset,
975
+ velocity,
976
+ direction,
977
+ active: !last,
978
+ first,
979
+ last,
980
+ event
981
+ };
982
+ },
983
+ []
984
+ );
985
+ const handlePointerMove = react.useCallback(
986
+ (event) => {
987
+ var _a, _b, _c, _d;
988
+ if (!isDragging.current || pointerId.current !== event.pointerId) return;
989
+ const position = Vector2.from(event.clientX, event.clientY);
990
+ velocityTracker.current.addSample(position);
991
+ if (!hasExceededThreshold.current) {
992
+ const distance = position.distanceTo(startPosition.current);
993
+ if (distance < threshold) return;
994
+ hasExceededThreshold.current = true;
995
+ const state2 = createGestureState(event, true, false);
996
+ (_b = (_a = handlersRef.current).onDragStart) == null ? void 0 : _b.call(_a, state2);
997
+ }
998
+ const state = createGestureState(event, false, false);
999
+ (_d = (_c = handlersRef.current).onDrag) == null ? void 0 : _d.call(_c, state);
1000
+ lastPosition.current = position;
1001
+ },
1002
+ [threshold, createGestureState]
1003
+ );
1004
+ const handlePointerUp = react.useCallback(
1005
+ (event) => {
1006
+ var _a, _b, _c, _d;
1007
+ if (!isDragging.current || pointerId.current !== event.pointerId) return;
1008
+ isDragging.current = false;
1009
+ pointerId.current = null;
1010
+ document.removeEventListener("pointermove", handlePointerMove);
1011
+ document.removeEventListener("pointerup", handlePointerUp);
1012
+ document.removeEventListener("pointercancel", handlePointerUp);
1013
+ if (hasExceededThreshold.current) {
1014
+ const state = createGestureState(event, false, true);
1015
+ (_b = (_a = handlersRef.current).onDragEnd) == null ? void 0 : _b.call(_a, state);
1016
+ const velocity = velocityTracker.current.getVelocity();
1017
+ if (velocity.magnitude > flickThreshold) {
1018
+ (_d = (_c = handlersRef.current).onFlick) == null ? void 0 : _d.call(_c, { ...state, flickVelocity: velocity });
1019
+ }
1020
+ }
1021
+ velocityTracker.current.reset();
1022
+ hasExceededThreshold.current = false;
1023
+ },
1024
+ [handlePointerMove, createGestureState, flickThreshold]
1025
+ );
1026
+ const onPointerDown = react.useCallback(
1027
+ (e) => {
1028
+ if (isDragging.current) return;
1029
+ const element = e.currentTarget;
1030
+ elementRef.current = element;
1031
+ element.setPointerCapture(e.pointerId);
1032
+ pointerId.current = e.pointerId;
1033
+ isDragging.current = true;
1034
+ hasExceededThreshold.current = false;
1035
+ const position = Vector2.from(e.clientX, e.clientY);
1036
+ startPosition.current = position;
1037
+ lastPosition.current = position;
1038
+ velocityTracker.current.reset();
1039
+ velocityTracker.current.addSample(position);
1040
+ document.addEventListener("pointermove", handlePointerMove);
1041
+ document.addEventListener("pointerup", handlePointerUp);
1042
+ document.addEventListener("pointercancel", handlePointerUp);
1043
+ },
1044
+ [handlePointerMove, handlePointerUp]
1045
+ );
1046
+ const onPointerEnter = react.useCallback(() => {
1047
+ onHover == null ? void 0 : onHover(true);
1048
+ }, [onHover]);
1049
+ const onPointerLeave = react.useCallback(() => {
1050
+ onHover == null ? void 0 : onHover(false);
1051
+ }, [onHover]);
1052
+ const handleFocus = react.useCallback(() => {
1053
+ onFocus == null ? void 0 : onFocus(true);
1054
+ }, [onFocus]);
1055
+ const handleBlur = react.useCallback(() => {
1056
+ onFocus == null ? void 0 : onFocus(false);
1057
+ }, [onFocus]);
1058
+ react.useEffect(() => {
1059
+ return () => {
1060
+ document.removeEventListener("pointermove", handlePointerMove);
1061
+ document.removeEventListener("pointerup", handlePointerUp);
1062
+ document.removeEventListener("pointercancel", handlePointerUp);
1063
+ };
1064
+ }, [handlePointerMove, handlePointerUp]);
1065
+ return {
1066
+ onPointerDown,
1067
+ onPointerEnter,
1068
+ onPointerLeave,
1069
+ onFocus: handleFocus,
1070
+ onBlur: handleBlur,
1071
+ style: preventTouch ? { touchAction: "none" } : {}
1072
+ };
1073
+ }
1074
+ function useDrag(options = {}) {
1075
+ const {
1076
+ initial = { x: 0, y: 0 },
1077
+ bounds,
1078
+ rubberBand = true,
1079
+ rubberBandFactor = 0.55,
1080
+ momentum = true,
1081
+ snapTo,
1082
+ snapThreshold = 50,
1083
+ axis = "both",
1084
+ springConfig,
1085
+ frictionConfig,
1086
+ onDragStart,
1087
+ onDrag,
1088
+ onDragEnd,
1089
+ onRest
1090
+ } = options;
1091
+ const globalConfig = usePhysicsConfig();
1092
+ const resolvedSpringConfig = react.useMemo(
1093
+ () => ({ ...DEFAULT_SPRING_CONFIG, ...globalConfig, ...springConfig }),
1094
+ [globalConfig, springConfig]
1095
+ );
1096
+ const resolvedFrictionConfig = react.useMemo(
1097
+ () => ({ ...DEFAULT_FRICTION_CONFIG, ...frictionConfig }),
1098
+ [frictionConfig]
1099
+ );
1100
+ const [state, setState] = react.useState({
1101
+ x: initial.x,
1102
+ y: initial.y,
1103
+ isDragging: false,
1104
+ isMomentum: false
1105
+ });
1106
+ const positionRef = react.useRef(Vector2.from(initial.x, initial.y));
1107
+ const startPositionRef = react.useRef(Vector2.zero());
1108
+ const dragOffsetRef = react.useRef(Vector2.zero());
1109
+ const velocityTracker = react.useRef(new VelocityTracker());
1110
+ const springRef = react.useRef(null);
1111
+ const momentumRef = react.useRef(null);
1112
+ const idRef = react.useRef(generatePhysicsId("drag"));
1113
+ const pointerIdRef = react.useRef(null);
1114
+ const handlersRef = react.useRef({ onDragStart, onDrag, onDragEnd, onRest });
1115
+ handlersRef.current = { onDragStart, onDrag, onDragEnd, onRest };
1116
+ const boundsVec = react.useMemo(() => {
1117
+ if (!bounds) return null;
1118
+ return {
1119
+ min: Vector2.from(bounds.left ?? -Infinity, bounds.top ?? -Infinity),
1120
+ max: Vector2.from(bounds.right ?? Infinity, bounds.bottom ?? Infinity)
1121
+ };
1122
+ }, [bounds]);
1123
+ const applyRubberBand = react.useCallback(
1124
+ (pos) => {
1125
+ if (!boundsVec || !rubberBand) return pos;
1126
+ let x = pos.x;
1127
+ let y = pos.y;
1128
+ if (pos.x < boundsVec.min.x) {
1129
+ const over = boundsVec.min.x - pos.x;
1130
+ x = boundsVec.min.x - over * rubberBandFactor;
1131
+ } else if (pos.x > boundsVec.max.x) {
1132
+ const over = pos.x - boundsVec.max.x;
1133
+ x = boundsVec.max.x + over * rubberBandFactor;
1134
+ }
1135
+ if (pos.y < boundsVec.min.y) {
1136
+ const over = boundsVec.min.y - pos.y;
1137
+ y = boundsVec.min.y - over * rubberBandFactor;
1138
+ } else if (pos.y > boundsVec.max.y) {
1139
+ const over = pos.y - boundsVec.max.y;
1140
+ y = boundsVec.max.y + over * rubberBandFactor;
1141
+ }
1142
+ return Vector2.from(x, y);
1143
+ },
1144
+ [boundsVec, rubberBand, rubberBandFactor]
1145
+ );
1146
+ const clampToBounds = react.useCallback(
1147
+ (pos) => {
1148
+ if (!boundsVec) return pos;
1149
+ return pos.clampComponents(boundsVec.min, boundsVec.max);
1150
+ },
1151
+ [boundsVec]
1152
+ );
1153
+ const findSnapPoint = react.useCallback(
1154
+ (pos, velocity) => {
1155
+ if (!snapTo || snapTo.length === 0) return null;
1156
+ const projectedPos = pos.add(velocity.multiply(0.1));
1157
+ let nearestPoint = null;
1158
+ let nearestDistance = Infinity;
1159
+ for (const point of snapTo) {
1160
+ const snapVec = Vector2.from(point.x, point.y);
1161
+ const distance = projectedPos.distanceTo(snapVec);
1162
+ if (distance < nearestDistance && distance < snapThreshold) {
1163
+ nearestDistance = distance;
1164
+ nearestPoint = snapVec;
1165
+ }
1166
+ }
1167
+ return nearestPoint;
1168
+ },
1169
+ [snapTo, snapThreshold]
1170
+ );
1171
+ const animateToTarget = react.useCallback(
1172
+ (target) => {
1173
+ springRef.current = new Spring(positionRef.current, resolvedSpringConfig);
1174
+ springRef.current.setTarget(target);
1175
+ PhysicsEngine.register(idRef.current, (deltaTime) => {
1176
+ var _a, _b;
1177
+ if (!springRef.current) return;
1178
+ const result = springRef.current.step(deltaTime);
1179
+ positionRef.current = result.position;
1180
+ setState((prev) => ({
1181
+ ...prev,
1182
+ x: result.position.x,
1183
+ y: result.position.y,
1184
+ isMomentum: false
1185
+ }));
1186
+ if (result.isSettled) {
1187
+ PhysicsEngine.unregister(idRef.current);
1188
+ (_b = (_a = handlersRef.current).onRest) == null ? void 0 : _b.call(_a, result.position);
1189
+ }
1190
+ });
1191
+ },
1192
+ [resolvedSpringConfig]
1193
+ );
1194
+ const handlePointerMove = react.useCallback(
1195
+ (e) => {
1196
+ var _a, _b;
1197
+ if (pointerIdRef.current !== e.pointerId) return;
1198
+ const currentPos = Vector2.from(e.clientX, e.clientY);
1199
+ velocityTracker.current.addSample(currentPos);
1200
+ let newPos = currentPos.subtract(dragOffsetRef.current);
1201
+ if (axis === "x") {
1202
+ newPos = Vector2.from(newPos.x, startPositionRef.current.y);
1203
+ } else if (axis === "y") {
1204
+ newPos = Vector2.from(startPositionRef.current.x, newPos.y);
1205
+ }
1206
+ newPos = applyRubberBand(newPos);
1207
+ positionRef.current = newPos;
1208
+ setState((prev) => ({
1209
+ ...prev,
1210
+ x: newPos.x,
1211
+ y: newPos.y
1212
+ }));
1213
+ (_b = (_a = handlersRef.current).onDrag) == null ? void 0 : _b.call(_a, newPos);
1214
+ },
1215
+ [axis, applyRubberBand]
1216
+ );
1217
+ const handlePointerUp = react.useCallback(
1218
+ (e) => {
1219
+ var _a, _b, _c, _d;
1220
+ if (pointerIdRef.current !== e.pointerId) return;
1221
+ pointerIdRef.current = null;
1222
+ document.removeEventListener("pointermove", handlePointerMove);
1223
+ document.removeEventListener("pointerup", handlePointerUp);
1224
+ document.removeEventListener("pointercancel", handlePointerUp);
1225
+ const velocity = velocityTracker.current.getVelocity();
1226
+ velocityTracker.current.reset();
1227
+ setState((prev) => ({ ...prev, isDragging: false }));
1228
+ (_b = (_a = handlersRef.current).onDragEnd) == null ? void 0 : _b.call(_a, positionRef.current, velocity);
1229
+ const snapPoint = findSnapPoint(positionRef.current, velocity);
1230
+ if (snapPoint) {
1231
+ animateToTarget(snapPoint);
1232
+ return;
1233
+ }
1234
+ if (boundsVec) {
1235
+ const clamped = clampToBounds(positionRef.current);
1236
+ if (!clamped.equals(positionRef.current)) {
1237
+ animateToTarget(clamped);
1238
+ return;
1239
+ }
1240
+ }
1241
+ if (momentum && velocity.magnitude > 100) {
1242
+ setState((prev) => ({ ...prev, isMomentum: true }));
1243
+ momentumRef.current = new Momentum(positionRef.current, resolvedFrictionConfig);
1244
+ momentumRef.current.start(positionRef.current, velocity);
1245
+ PhysicsEngine.register(idRef.current, (deltaTime) => {
1246
+ var _a2, _b2;
1247
+ if (!momentumRef.current) return;
1248
+ const result = momentumRef.current.step(deltaTime);
1249
+ let newPos = result.position;
1250
+ if (boundsVec) {
1251
+ const clamped = clampToBounds(newPos);
1252
+ if (!clamped.equals(newPos)) {
1253
+ momentumRef.current.stop();
1254
+ PhysicsEngine.unregister(idRef.current);
1255
+ positionRef.current = newPos;
1256
+ animateToTarget(clamped);
1257
+ return;
1258
+ }
1259
+ }
1260
+ positionRef.current = newPos;
1261
+ setState((prev) => ({
1262
+ ...prev,
1263
+ x: newPos.x,
1264
+ y: newPos.y,
1265
+ isMomentum: result.isActive
1266
+ }));
1267
+ if (!result.isActive) {
1268
+ PhysicsEngine.unregister(idRef.current);
1269
+ (_b2 = (_a2 = handlersRef.current).onRest) == null ? void 0 : _b2.call(_a2, newPos);
1270
+ }
1271
+ });
1272
+ } else {
1273
+ (_d = (_c = handlersRef.current).onRest) == null ? void 0 : _d.call(_c, positionRef.current);
1274
+ }
1275
+ },
1276
+ [
1277
+ handlePointerMove,
1278
+ momentum,
1279
+ boundsVec,
1280
+ clampToBounds,
1281
+ findSnapPoint,
1282
+ animateToTarget,
1283
+ resolvedFrictionConfig
1284
+ ]
1285
+ );
1286
+ const onPointerDown = react.useCallback(
1287
+ (e) => {
1288
+ var _a, _b;
1289
+ if (pointerIdRef.current !== null) return;
1290
+ PhysicsEngine.unregister(idRef.current);
1291
+ pointerIdRef.current = e.pointerId;
1292
+ const element = e.currentTarget;
1293
+ element.setPointerCapture(e.pointerId);
1294
+ const pointerPos = Vector2.from(e.clientX, e.clientY);
1295
+ dragOffsetRef.current = pointerPos.subtract(positionRef.current);
1296
+ startPositionRef.current = positionRef.current;
1297
+ velocityTracker.current.reset();
1298
+ velocityTracker.current.addSample(pointerPos);
1299
+ setState((prev) => ({ ...prev, isDragging: true, isMomentum: false }));
1300
+ (_b = (_a = handlersRef.current).onDragStart) == null ? void 0 : _b.call(_a, positionRef.current);
1301
+ document.addEventListener("pointermove", handlePointerMove);
1302
+ document.addEventListener("pointerup", handlePointerUp);
1303
+ document.addEventListener("pointercancel", handlePointerUp);
1304
+ },
1305
+ [handlePointerMove, handlePointerUp]
1306
+ );
1307
+ const setPosition = react.useCallback((position) => {
1308
+ PhysicsEngine.unregister(idRef.current);
1309
+ positionRef.current = Vector2.from(position.x, position.y);
1310
+ setState((prev) => ({
1311
+ ...prev,
1312
+ x: position.x,
1313
+ y: position.y,
1314
+ isDragging: false,
1315
+ isMomentum: false
1316
+ }));
1317
+ }, []);
1318
+ const snapToPosition = react.useCallback(
1319
+ (position) => {
1320
+ animateToTarget(Vector2.from(position.x, position.y));
1321
+ },
1322
+ [animateToTarget]
1323
+ );
1324
+ react.useEffect(() => {
1325
+ return () => {
1326
+ PhysicsEngine.unregister(idRef.current);
1327
+ document.removeEventListener("pointermove", handlePointerMove);
1328
+ document.removeEventListener("pointerup", handlePointerUp);
1329
+ document.removeEventListener("pointercancel", handlePointerUp);
1330
+ };
1331
+ }, [handlePointerMove, handlePointerUp]);
1332
+ const style = react.useMemo(
1333
+ () => ({
1334
+ transform: `translate3d(${state.x}px, ${state.y}px, 0)`,
1335
+ willChange: state.isDragging || state.isMomentum ? "transform" : "auto",
1336
+ cursor: state.isDragging ? "grabbing" : "grab"
1337
+ }),
1338
+ [state.x, state.y, state.isDragging, state.isMomentum]
1339
+ );
1340
+ return {
1341
+ x: state.x,
1342
+ y: state.y,
1343
+ isDragging: state.isDragging,
1344
+ isMomentum: state.isMomentum,
1345
+ style,
1346
+ bind: {
1347
+ onPointerDown,
1348
+ style: { touchAction: "none" }
1349
+ },
1350
+ setPosition,
1351
+ snapToPosition
1352
+ };
1353
+ }
1354
+ function useStretch(options) {
1355
+ const {
1356
+ velocity,
1357
+ axis = "both",
1358
+ intensity = 0.12,
1359
+ maxVelocity = 2e3
1360
+ } = options;
1361
+ return react.useMemo(() => {
1362
+ const vel = velocity instanceof Vector2 ? velocity : Vector2.from(velocity.x, velocity.y);
1363
+ const normalizedX = Math.min(Math.abs(vel.x) / maxVelocity, 1);
1364
+ const normalizedY = Math.min(Math.abs(vel.y) / maxVelocity, 1);
1365
+ const easedX = easeOutQuad(normalizedX);
1366
+ const easedY = easeOutQuad(normalizedY);
1367
+ let scaleX = 1;
1368
+ let scaleY = 1;
1369
+ if (axis === "x" || axis === "both") {
1370
+ const stretchX = 1 + easedX * intensity;
1371
+ const compressY = 1 - easedX * intensity * 0.5;
1372
+ if (axis === "x") {
1373
+ scaleX = stretchX;
1374
+ scaleY = compressY;
1375
+ } else {
1376
+ scaleX = stretchX;
1377
+ }
1378
+ }
1379
+ if (axis === "y" || axis === "both") {
1380
+ const stretchY = 1 + easedY * intensity;
1381
+ const compressX = 1 - easedY * intensity * 0.5;
1382
+ if (axis === "y") {
1383
+ scaleY = stretchY;
1384
+ scaleX = compressX;
1385
+ } else {
1386
+ scaleY = stretchY;
1387
+ }
1388
+ }
1389
+ if (axis === "both" && normalizedX > 0 && normalizedY > 0) {
1390
+ if (normalizedX > normalizedY) {
1391
+ scaleX = 1 + easedX * intensity;
1392
+ scaleY = 1 - easedX * intensity * 0.3 + easedY * intensity * 0.5;
1393
+ } else {
1394
+ scaleY = 1 + easedY * intensity;
1395
+ scaleX = 1 - easedY * intensity * 0.3 + easedX * intensity * 0.5;
1396
+ }
1397
+ }
1398
+ scaleX = Math.max(0.85, Math.min(1.15, scaleX));
1399
+ scaleY = Math.max(0.85, Math.min(1.15, scaleY));
1400
+ return {
1401
+ scaleX,
1402
+ scaleY,
1403
+ style: {
1404
+ transform: `scale3d(${scaleX}, ${scaleY}, 1)`,
1405
+ willChange: scaleX !== 1 || scaleY !== 1 ? "transform" : "auto"
1406
+ }
1407
+ };
1408
+ }, [velocity, axis, intensity, maxVelocity]);
1409
+ }
1410
+ function easeOutQuad(t) {
1411
+ return t * (2 - t);
1412
+ }
1413
+ function combineStretchStyle(positionStyle, stretchStyle) {
1414
+ const positionTransform = positionStyle.transform || "";
1415
+ const stretchTransform = stretchStyle.transform || "";
1416
+ return {
1417
+ ...positionStyle,
1418
+ transform: `${positionTransform} ${stretchTransform}`.trim(),
1419
+ willChange: positionStyle.willChange === "transform" || stretchStyle.willChange === "transform" ? "transform" : "auto"
1420
+ };
1421
+ }
1422
+ function useLift(options = {}) {
1423
+ const {
1424
+ trigger = "hover",
1425
+ scale: targetScale = 1.03,
1426
+ shadow = true,
1427
+ shadowIntensity = 1,
1428
+ springConfig,
1429
+ onLift
1430
+ } = options;
1431
+ const [isLifted, setIsLifted] = react.useState(false);
1432
+ const { value: scale } = useSpring1D({
1433
+ to: isLifted ? targetScale : 1,
1434
+ config: {
1435
+ tension: 300,
1436
+ friction: 20,
1437
+ ...springConfig
1438
+ }
1439
+ });
1440
+ const handleLift = react.useCallback(
1441
+ (lifted) => {
1442
+ setIsLifted(lifted);
1443
+ onLift == null ? void 0 : onLift(lifted);
1444
+ },
1445
+ [onLift]
1446
+ );
1447
+ const bind = react.useMemo(() => {
1448
+ switch (trigger) {
1449
+ case "hover":
1450
+ return {
1451
+ onPointerEnter: () => handleLift(true),
1452
+ onPointerLeave: () => handleLift(false)
1453
+ };
1454
+ case "drag":
1455
+ return {
1456
+ onPointerDown: () => handleLift(true),
1457
+ onPointerUp: () => handleLift(false)
1458
+ };
1459
+ case "focus":
1460
+ return {
1461
+ onFocus: () => handleLift(true),
1462
+ onBlur: () => handleLift(false)
1463
+ };
1464
+ case "active":
1465
+ return {
1466
+ onPointerDown: () => handleLift(true),
1467
+ onPointerUp: () => handleLift(false),
1468
+ onPointerLeave: () => handleLift(false)
1469
+ };
1470
+ default:
1471
+ return {};
1472
+ }
1473
+ }, [trigger, handleLift]);
1474
+ const shadowStyle = react.useMemo(() => {
1475
+ if (!shadow) return {};
1476
+ const liftAmount = (scale - 1) / (targetScale - 1);
1477
+ const clampedLift = Math.max(0, Math.min(1, liftAmount));
1478
+ const blur = 8 + clampedLift * 24 * shadowIntensity;
1479
+ const spread = clampedLift * 4 * shadowIntensity;
1480
+ const yOffset = 2 + clampedLift * 12 * shadowIntensity;
1481
+ const opacity = 0.08 + clampedLift * 0.12 * shadowIntensity;
1482
+ return {
1483
+ boxShadow: `0 ${yOffset}px ${blur}px ${spread}px rgba(0, 0, 0, ${opacity})`
1484
+ };
1485
+ }, [scale, targetScale, shadow, shadowIntensity]);
1486
+ const style = react.useMemo(
1487
+ () => ({
1488
+ transform: `scale3d(${scale}, ${scale}, 1)`,
1489
+ transformOrigin: "center center",
1490
+ willChange: scale !== 1 ? "transform, box-shadow" : "auto",
1491
+ ...shadowStyle
1492
+ }),
1493
+ [scale, shadowStyle]
1494
+ );
1495
+ return {
1496
+ isLifted,
1497
+ scale,
1498
+ style,
1499
+ bind,
1500
+ setLifted: handleLift
1501
+ };
1502
+ }
1503
+ function combineLiftStyle(baseStyle, liftStyle) {
1504
+ const baseTransform = baseStyle.transform || "";
1505
+ const liftTransform = liftStyle.transform || "";
1506
+ return {
1507
+ ...baseStyle,
1508
+ ...liftStyle,
1509
+ transform: `${baseTransform} ${liftTransform}`.trim()
1510
+ };
1511
+ }
1512
+ function useFlick(options = {}) {
1513
+ const {
1514
+ initial = { x: 0, y: 0 },
1515
+ threshold = 500,
1516
+ friction,
1517
+ axis = "both",
1518
+ onFlickStart,
1519
+ onFlick,
1520
+ onFlickEnd
1521
+ } = options;
1522
+ const resolvedFriction = react.useMemo(
1523
+ () => ({ ...DEFAULT_FRICTION_CONFIG, ...friction }),
1524
+ [friction]
1525
+ );
1526
+ const [state, setState] = react.useState({
1527
+ x: initial.x,
1528
+ y: initial.y,
1529
+ isFlicking: false,
1530
+ velocity: Vector2.zero()
1531
+ });
1532
+ const positionRef = react.useRef(Vector2.from(initial.x, initial.y));
1533
+ const momentumRef = react.useRef(null);
1534
+ const velocityTracker = react.useRef(new VelocityTracker());
1535
+ const idRef = react.useRef(generatePhysicsId("flick"));
1536
+ const handlersRef = react.useRef({ onFlickStart, onFlick, onFlickEnd });
1537
+ handlersRef.current = { onFlickStart, onFlick, onFlickEnd };
1538
+ const startMomentum = react.useCallback(
1539
+ (velocity) => {
1540
+ var _a, _b;
1541
+ let constrainedVelocity = velocity;
1542
+ if (axis === "x") {
1543
+ constrainedVelocity = Vector2.from(velocity.x, 0);
1544
+ } else if (axis === "y") {
1545
+ constrainedVelocity = Vector2.from(0, velocity.y);
1546
+ }
1547
+ momentumRef.current = new Momentum(positionRef.current, resolvedFriction);
1548
+ momentumRef.current.start(positionRef.current, constrainedVelocity);
1549
+ setState((prev) => ({
1550
+ ...prev,
1551
+ isFlicking: true,
1552
+ velocity: constrainedVelocity
1553
+ }));
1554
+ (_b = (_a = handlersRef.current).onFlickStart) == null ? void 0 : _b.call(_a, constrainedVelocity);
1555
+ PhysicsEngine.register(idRef.current, (deltaTime) => {
1556
+ var _a2, _b2, _c, _d;
1557
+ if (!momentumRef.current) return;
1558
+ const result = momentumRef.current.step(deltaTime);
1559
+ let newPos = result.position;
1560
+ if (axis === "x") {
1561
+ newPos = Vector2.from(newPos.x, positionRef.current.y);
1562
+ } else if (axis === "y") {
1563
+ newPos = Vector2.from(positionRef.current.x, newPos.y);
1564
+ }
1565
+ positionRef.current = newPos;
1566
+ setState({
1567
+ x: newPos.x,
1568
+ y: newPos.y,
1569
+ isFlicking: result.isActive,
1570
+ velocity: result.velocity
1571
+ });
1572
+ (_b2 = (_a2 = handlersRef.current).onFlick) == null ? void 0 : _b2.call(_a2, newPos, result.velocity);
1573
+ if (!result.isActive) {
1574
+ PhysicsEngine.unregister(idRef.current);
1575
+ (_d = (_c = handlersRef.current).onFlickEnd) == null ? void 0 : _d.call(_c, newPos);
1576
+ }
1577
+ });
1578
+ },
1579
+ [axis, resolvedFriction]
1580
+ );
1581
+ const flick = react.useCallback(
1582
+ (velocity) => {
1583
+ PhysicsEngine.unregister(idRef.current);
1584
+ velocityTracker.current.reset();
1585
+ startMomentum(Vector2.from(velocity.x, velocity.y));
1586
+ },
1587
+ [startMomentum]
1588
+ );
1589
+ const stop = react.useCallback(() => {
1590
+ var _a;
1591
+ PhysicsEngine.unregister(idRef.current);
1592
+ (_a = momentumRef.current) == null ? void 0 : _a.stop();
1593
+ velocityTracker.current.reset();
1594
+ setState((prev) => ({
1595
+ ...prev,
1596
+ isFlicking: false,
1597
+ velocity: Vector2.zero()
1598
+ }));
1599
+ }, []);
1600
+ const setPosition = react.useCallback(
1601
+ (position) => {
1602
+ stop();
1603
+ positionRef.current = Vector2.from(position.x, position.y);
1604
+ setState({
1605
+ x: position.x,
1606
+ y: position.y,
1607
+ isFlicking: false,
1608
+ velocity: Vector2.zero()
1609
+ });
1610
+ },
1611
+ [stop]
1612
+ );
1613
+ const recordSample = react.useCallback((position) => {
1614
+ velocityTracker.current.addSample(Vector2.from(position.x, position.y));
1615
+ positionRef.current = Vector2.from(position.x, position.y);
1616
+ setState((prev) => ({
1617
+ ...prev,
1618
+ x: position.x,
1619
+ y: position.y
1620
+ }));
1621
+ }, []);
1622
+ const getCurrentVelocity = react.useCallback(() => {
1623
+ return velocityTracker.current.getVelocity();
1624
+ }, []);
1625
+ const release = react.useCallback(
1626
+ (position) => {
1627
+ positionRef.current = Vector2.from(position.x, position.y);
1628
+ const velocity = velocityTracker.current.getVelocity();
1629
+ velocityTracker.current.reset();
1630
+ if (velocity.magnitude >= threshold) {
1631
+ startMomentum(velocity);
1632
+ return true;
1633
+ }
1634
+ setState((prev) => ({
1635
+ ...prev,
1636
+ x: position.x,
1637
+ y: position.y,
1638
+ isFlicking: false,
1639
+ velocity: Vector2.zero()
1640
+ }));
1641
+ return false;
1642
+ },
1643
+ [threshold, startMomentum]
1644
+ );
1645
+ react.useEffect(() => {
1646
+ return () => {
1647
+ PhysicsEngine.unregister(idRef.current);
1648
+ };
1649
+ }, []);
1650
+ const style = react.useMemo(
1651
+ () => ({
1652
+ transform: `translate3d(${state.x}px, ${state.y}px, 0)`,
1653
+ willChange: state.isFlicking ? "transform" : "auto"
1654
+ }),
1655
+ [state.x, state.y, state.isFlicking]
1656
+ );
1657
+ return {
1658
+ x: state.x,
1659
+ y: state.y,
1660
+ isFlicking: state.isFlicking,
1661
+ velocity: state.velocity,
1662
+ style,
1663
+ flick,
1664
+ stop,
1665
+ setPosition,
1666
+ recordSample,
1667
+ getCurrentVelocity,
1668
+ release
1669
+ };
1670
+ }
1671
+ const Draggable = react.forwardRef(
1672
+ ({
1673
+ children,
1674
+ initial = { x: 0, y: 0 },
1675
+ bounds,
1676
+ rubberBand = true,
1677
+ momentum = true,
1678
+ lift: enableLift = true,
1679
+ stretch: enableStretch = true,
1680
+ snapTo,
1681
+ axis = "both",
1682
+ springConfig,
1683
+ className,
1684
+ style: customStyle,
1685
+ onDragStart,
1686
+ onDrag,
1687
+ onDragEnd,
1688
+ onRest
1689
+ }, ref) => {
1690
+ const physicsContext = usePhysicsContext();
1691
+ const {
1692
+ isDragging,
1693
+ isMomentum,
1694
+ style: dragStyle,
1695
+ bind
1696
+ } = useDrag({
1697
+ initial,
1698
+ bounds,
1699
+ rubberBand,
1700
+ momentum,
1701
+ snapTo,
1702
+ axis,
1703
+ springConfig: { ...physicsContext.spring, ...springConfig },
1704
+ onDragStart: (pos) => onDragStart == null ? void 0 : onDragStart(pos.toObject()),
1705
+ onDrag: (pos) => onDrag == null ? void 0 : onDrag(pos.toObject()),
1706
+ onDragEnd: (pos, vel) => onDragEnd == null ? void 0 : onDragEnd(pos.toObject(), vel.toObject()),
1707
+ onRest: (pos) => onRest == null ? void 0 : onRest(pos.toObject())
1708
+ });
1709
+ const { style: liftStyle, bind: liftBind } = useLift({
1710
+ trigger: "drag",
1711
+ scale: physicsContext.lift.scale,
1712
+ shadowIntensity: physicsContext.lift.shadowIntensity
1713
+ });
1714
+ const velocity = react.useMemo(() => {
1715
+ if (!isDragging && !isMomentum) return Vector2.zero();
1716
+ return Vector2.from(0, 0);
1717
+ }, [isDragging, isMomentum]);
1718
+ const { style: stretchStyle } = useStretch({
1719
+ velocity,
1720
+ intensity: physicsContext.stretch.intensity,
1721
+ maxVelocity: physicsContext.stretch.maxVelocity
1722
+ });
1723
+ const combinedStyle = react.useMemo(() => {
1724
+ let result = { ...dragStyle };
1725
+ if (enableLift && isDragging) {
1726
+ result = combineLiftStyle(result, liftStyle);
1727
+ }
1728
+ if (enableStretch) {
1729
+ result = combineStretchStyle(result, stretchStyle);
1730
+ }
1731
+ return {
1732
+ ...result,
1733
+ ...customStyle,
1734
+ position: "relative",
1735
+ userSelect: "none"
1736
+ };
1737
+ }, [dragStyle, liftStyle, stretchStyle, enableLift, enableStretch, isDragging, customStyle]);
1738
+ const combinedBind = react.useMemo(() => {
1739
+ return {
1740
+ ...bind,
1741
+ onPointerDown: (e) => {
1742
+ var _a;
1743
+ bind.onPointerDown(e);
1744
+ if (enableLift) {
1745
+ (_a = liftBind.onPointerDown) == null ? void 0 : _a.call(liftBind);
1746
+ }
1747
+ },
1748
+ onPointerUp: () => {
1749
+ var _a;
1750
+ if (enableLift) {
1751
+ (_a = liftBind.onPointerUp) == null ? void 0 : _a.call(liftBind);
1752
+ }
1753
+ }
1754
+ };
1755
+ }, [bind, liftBind, enableLift]);
1756
+ return /* @__PURE__ */ jsxRuntime.jsx(
1757
+ "div",
1758
+ {
1759
+ ref,
1760
+ className,
1761
+ ...combinedBind,
1762
+ style: combinedStyle,
1763
+ children
1764
+ }
1765
+ );
1766
+ }
1767
+ );
1768
+ Draggable.displayName = "Draggable";
1769
+ const Card = react.forwardRef(
1770
+ ({
1771
+ children,
1772
+ lift: enableLift = true,
1773
+ pressable = true,
1774
+ liftScale,
1775
+ pressScale = 0.98,
1776
+ glass = false,
1777
+ glassBlur = 20,
1778
+ springConfig,
1779
+ className,
1780
+ style: customStyle,
1781
+ onClick,
1782
+ onHover,
1783
+ onPress
1784
+ }, ref) => {
1785
+ const physicsContext = usePhysicsContext();
1786
+ const [isPressed, setIsPressed] = react.useState(false);
1787
+ const resolvedLiftScale = liftScale ?? physicsContext.lift.scale;
1788
+ const { style: liftStyle, bind: liftBind, isLifted } = useLift({
1789
+ trigger: "hover",
1790
+ scale: resolvedLiftScale,
1791
+ shadowIntensity: physicsContext.lift.shadowIntensity,
1792
+ springConfig: { ...physicsContext.spring, ...springConfig },
1793
+ onLift: onHover
1794
+ });
1795
+ const { value: pressScaleValue } = useSpring1D({
1796
+ to: isPressed ? pressScale : 1,
1797
+ config: {
1798
+ tension: 400,
1799
+ friction: 25,
1800
+ ...springConfig
1801
+ }
1802
+ });
1803
+ const handlePointerDown = react.useCallback(() => {
1804
+ if (pressable) {
1805
+ setIsPressed(true);
1806
+ onPress == null ? void 0 : onPress(true);
1807
+ }
1808
+ }, [pressable, onPress]);
1809
+ const handlePointerUp = react.useCallback(() => {
1810
+ if (pressable) {
1811
+ setIsPressed(false);
1812
+ onPress == null ? void 0 : onPress(false);
1813
+ }
1814
+ }, [pressable, onPress]);
1815
+ const handlePointerLeave = react.useCallback(() => {
1816
+ if (isPressed) {
1817
+ setIsPressed(false);
1818
+ onPress == null ? void 0 : onPress(false);
1819
+ }
1820
+ }, [isPressed, onPress]);
1821
+ const glassStyles = glass ? {
1822
+ background: "rgba(255, 255, 255, 0.1)",
1823
+ backdropFilter: `blur(${glassBlur}px)`,
1824
+ WebkitBackdropFilter: `blur(${glassBlur}px)`,
1825
+ border: "1px solid rgba(255, 255, 255, 0.18)"
1826
+ } : {};
1827
+ const combinedStyle = react.useMemo(() => {
1828
+ const liftTransform = enableLift ? liftStyle.transform || "" : "";
1829
+ const pressTransform = pressable ? `scale(${pressScaleValue})` : "";
1830
+ const transform = `${liftTransform} ${pressTransform}`.trim() || void 0;
1831
+ return {
1832
+ ...glassStyles,
1833
+ ...liftStyle,
1834
+ ...customStyle,
1835
+ transform,
1836
+ transformOrigin: "center center",
1837
+ cursor: onClick ? "pointer" : "default",
1838
+ willChange: isLifted || isPressed ? "transform, box-shadow" : "auto"
1839
+ };
1840
+ }, [
1841
+ liftStyle,
1842
+ pressScaleValue,
1843
+ enableLift,
1844
+ pressable,
1845
+ glassStyles,
1846
+ customStyle,
1847
+ onClick,
1848
+ isLifted,
1849
+ isPressed
1850
+ ]);
1851
+ return /* @__PURE__ */ jsxRuntime.jsx(
1852
+ "div",
1853
+ {
1854
+ ref,
1855
+ className,
1856
+ style: combinedStyle,
1857
+ onClick,
1858
+ onPointerEnter: liftBind.onPointerEnter,
1859
+ onPointerLeave: () => {
1860
+ var _a;
1861
+ (_a = liftBind.onPointerLeave) == null ? void 0 : _a.call(liftBind);
1862
+ handlePointerLeave();
1863
+ },
1864
+ onPointerDown: handlePointerDown,
1865
+ onPointerUp: handlePointerUp,
1866
+ children
1867
+ }
1868
+ );
1869
+ }
1870
+ );
1871
+ Card.displayName = "Card";
1872
+ const cardBaseStyles = {
1873
+ padding: "24px",
1874
+ borderRadius: "16px",
1875
+ background: "white",
1876
+ boxShadow: "0 4px 12px rgba(0, 0, 0, 0.08)"
1877
+ };
1878
+ exports.Card = Card;
1879
+ exports.DEFAULT_FRICTION_CONFIG = DEFAULT_FRICTION_CONFIG;
1880
+ exports.DEFAULT_SPRING_CONFIG = DEFAULT_SPRING_CONFIG;
1881
+ exports.Draggable = Draggable;
1882
+ exports.Momentum = Momentum;
1883
+ exports.Momentum1D = Momentum1D;
1884
+ exports.PhysicsEngine = PhysicsEngine;
1885
+ exports.PhysicsProvider = PhysicsProvider;
1886
+ exports.Spring = Spring;
1887
+ exports.Spring1D = Spring1D;
1888
+ exports.Vector2 = Vector2;
1889
+ exports.VelocityTracker = VelocityTracker;
1890
+ exports.VelocityTracker1D = VelocityTracker1D;
1891
+ exports.cardBaseStyles = cardBaseStyles;
1892
+ exports.combineLiftStyle = combineLiftStyle;
1893
+ exports.combineStretchStyle = combineStretchStyle;
1894
+ exports.generatePhysicsId = generatePhysicsId;
1895
+ exports.gentle = gentle;
1896
+ exports.getFrictionConfig = getFrictionConfig;
1897
+ exports.getPreset = getPreset;
1898
+ exports.getSpringConfig = getSpringConfig;
1899
+ exports.ios = ios;
1900
+ exports.presets = presets;
1901
+ exports.smooth = smooth;
1902
+ exports.snappy = snappy;
1903
+ exports.stiff = stiff;
1904
+ exports.useDrag = useDrag;
1905
+ exports.useFlick = useFlick;
1906
+ exports.useFrictionConfig = useFrictionConfig;
1907
+ exports.useGesture = useGesture;
1908
+ exports.useLift = useLift;
1909
+ exports.useLiftConfig = useLiftConfig;
1910
+ exports.usePhysicsConfig = usePhysicsConfig;
1911
+ exports.usePhysicsContext = usePhysicsContext;
1912
+ exports.useSpring = useSpring;
1913
+ exports.useSpring1D = useSpring1D;
1914
+ exports.useStretch = useStretch;
1915
+ exports.useStretchConfig = useStretchConfig;
1916
+ //# sourceMappingURL=index.cjs.map