@diabolic/pointy 1.0.0 → 1.0.1

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/src/pointy.js CHANGED
@@ -472,6 +472,8 @@ class Pointy {
472
472
  this.isVisible = false;
473
473
  this.isPointingUp = true; // Always start pointing up
474
474
  this.lastTargetY = null;
475
+ this._targetYHistory = []; // Track Y positions for velocity detection
476
+ this._lastDirectionChangeTime = 0; // Debounce direction changes
475
477
  this.manualDirection = null; // 'up', 'down', or null (auto)
476
478
  this.moveTimeout = null;
477
479
  this._hasShownBefore = false; // For intro animation
@@ -578,18 +580,37 @@ class Pointy {
578
580
  if (this.manualDirection !== null) {
579
581
  this.isPointingUp = this.manualDirection === 'up';
580
582
  } else {
581
- // Auto: Check if target is above or below previous position
583
+ // Auto: Track velocity over time to detect movement direction
582
584
  const currentTargetY = targetRect.top + scrollY;
583
- if (this.lastTargetY !== null) {
584
- const threshold = 50;
585
- if (currentTargetY < this.lastTargetY - threshold) {
586
- // Target moved UP - pointer below target, pointing up
587
- this.isPointingUp = true;
588
- } else if (currentTargetY > this.lastTargetY + threshold) {
589
- // Target moved DOWN - pointer above target, pointing down
590
- this.isPointingUp = false;
585
+ const now = Date.now();
586
+
587
+ // Add to history with timestamp
588
+ this._targetYHistory.push({ y: currentTargetY, time: now });
589
+
590
+ // Keep only last 200ms of history
591
+ const historyWindow = 200;
592
+ this._targetYHistory = this._targetYHistory.filter(h => now - h.time < historyWindow);
593
+
594
+ // Calculate velocity if we have enough history
595
+ if (this._targetYHistory.length >= 2) {
596
+ const oldest = this._targetYHistory[0];
597
+ const newest = this._targetYHistory[this._targetYHistory.length - 1];
598
+ const deltaY = newest.y - oldest.y;
599
+ const deltaTime = newest.time - oldest.time;
600
+
601
+ // Only change direction if significant movement and debounce (300ms between changes)
602
+ const velocityThreshold = 30; // pixels moved in the history window
603
+ const debounceTime = 300;
604
+
605
+ if (Math.abs(deltaY) > velocityThreshold && (now - this._lastDirectionChangeTime) > debounceTime) {
606
+ const newDirection = deltaY < 0; // Moving up = true, moving down = false
607
+ if (newDirection !== this.isPointingUp) {
608
+ this.isPointingUp = newDirection;
609
+ this._lastDirectionChangeTime = now;
610
+ }
591
611
  }
592
612
  }
613
+
593
614
  this.lastTargetY = currentTargetY;
594
615
  }
595
616
 
@@ -1917,14 +1938,17 @@ class Pointy {
1917
1938
  pointTo(target, content, direction) {
1918
1939
  const previousTarget = this.targetElement;
1919
1940
 
1941
+ // Determine actual direction ('auto' means will be calculated in updatePosition)
1942
+ const actualDirection = direction || 'auto';
1943
+
1920
1944
  this._emit('beforePointTo', {
1921
1945
  target: Pointy.getTargetElement(target),
1922
1946
  content: content,
1923
- direction: direction,
1947
+ direction: actualDirection,
1924
1948
  fromTarget: previousTarget
1925
1949
  });
1926
1950
 
1927
- // Set manual direction
1951
+ // Set manual direction (null means auto)
1928
1952
  this.manualDirection = direction || null;
1929
1953
 
1930
1954
  // Pause floating animation during movement
@@ -1940,17 +1964,6 @@ class Pointy {
1940
1964
  content: content
1941
1965
  });
1942
1966
 
1943
- this.moveTimeout = setTimeout(() => {
1944
- this.container.classList.remove(this.classNames.moving);
1945
- this._emit('pointToComplete', { target: this.targetElement, content: content });
1946
- this._emit('animationEnd', {
1947
- fromTarget: previousTarget,
1948
- toTarget: this.targetElement,
1949
- type: 'pointTo',
1950
- content: content
1951
- });
1952
- }, this.animationDuration);
1953
-
1954
1967
  this.targetElement = toTarget;
1955
1968
 
1956
1969
  if (content !== undefined) {
@@ -1962,7 +1975,21 @@ class Pointy {
1962
1975
 
1963
1976
  this.updatePosition();
1964
1977
 
1965
- this._emit('pointTo', { target: this.targetElement, content: content, direction: direction });
1978
+ // Get the resolved direction after updatePosition calculates it
1979
+ const resolvedDirection = this.isPointingUp ? 'up' : 'down';
1980
+
1981
+ this.moveTimeout = setTimeout(() => {
1982
+ this.container.classList.remove(this.classNames.moving);
1983
+ this._emit('pointToComplete', { target: this.targetElement, content: content, direction: resolvedDirection });
1984
+ this._emit('animationEnd', {
1985
+ fromTarget: previousTarget,
1986
+ toTarget: this.targetElement,
1987
+ type: 'pointTo',
1988
+ content: content
1989
+ });
1990
+ }, this.animationDuration);
1991
+
1992
+ this._emit('pointTo', { target: this.targetElement, content: content, direction: resolvedDirection });
1966
1993
 
1967
1994
  // Make sure it's visible
1968
1995
  if (!this.isVisible) {