tracky-mouse 2.7.0 → 2.8.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.
Files changed (69) hide show
  1. package/lib/face-landmarks-detection.min.js +1 -1
  2. package/lib/face_mesh/face_mesh.js +1 -1
  3. package/locales/ar/translation.json +5 -1
  4. package/locales/ar-EG/translation.json +5 -1
  5. package/locales/bg/translation.json +5 -1
  6. package/locales/bn/translation.json +5 -1
  7. package/locales/ca/translation.json +5 -1
  8. package/locales/ce/translation.json +5 -1
  9. package/locales/ceb/translation.json +6 -2
  10. package/locales/cs/translation.json +5 -1
  11. package/locales/da/translation.json +5 -1
  12. package/locales/de/translation.json +5 -1
  13. package/locales/el/translation.json +5 -1
  14. package/locales/emoji/emoji-translation-notes.md +1 -0
  15. package/locales/emoji/translation.json +9 -5
  16. package/locales/en/translation.json +5 -1
  17. package/locales/eo/translation.json +5 -1
  18. package/locales/es/translation.json +5 -1
  19. package/locales/eu/translation.json +5 -1
  20. package/locales/fa/translation.json +5 -1
  21. package/locales/fi/translation.json +5 -1
  22. package/locales/fr/translation.json +5 -1
  23. package/locales/gu/translation.json +5 -1
  24. package/locales/ha/translation.json +5 -1
  25. package/locales/he/translation.json +5 -1
  26. package/locales/hi/translation.json +5 -1
  27. package/locales/hr/translation.json +5 -1
  28. package/locales/hu/translation.json +5 -1
  29. package/locales/hy/translation.json +5 -1
  30. package/locales/id/translation.json +5 -1
  31. package/locales/it/translation.json +5 -1
  32. package/locales/ja/translation.json +5 -1
  33. package/locales/jv/translation.json +6 -2
  34. package/locales/ko/translation.json +5 -1
  35. package/locales/mr/translation.json +5 -1
  36. package/locales/ms/translation.json +5 -1
  37. package/locales/nan/translation.json +5 -1
  38. package/locales/nb/translation.json +5 -1
  39. package/locales/nl/translation.json +5 -1
  40. package/locales/pa/translation.json +5 -1
  41. package/locales/pl/translation.json +5 -1
  42. package/locales/pt/translation.json +5 -1
  43. package/locales/pt-BR/translation.json +5 -1
  44. package/locales/ro/translation.json +5 -1
  45. package/locales/ru/translation.json +5 -1
  46. package/locales/sk/translation.json +5 -1
  47. package/locales/sl/translation.json +5 -1
  48. package/locales/sr/translation.json +5 -1
  49. package/locales/sv/translation.json +5 -1
  50. package/locales/sw/translation.json +5 -1
  51. package/locales/ta/translation.json +5 -1
  52. package/locales/te/translation.json +5 -1
  53. package/locales/th/translation.json +5 -1
  54. package/locales/tl/translation.json +6 -2
  55. package/locales/tr/translation.json +5 -1
  56. package/locales/tt/translation.json +5 -1
  57. package/locales/uk/translation.json +5 -1
  58. package/locales/ur/translation.json +5 -1
  59. package/locales/uz/translation.json +5 -1
  60. package/locales/vi/translation.json +5 -1
  61. package/locales/war/translation.json +6 -2
  62. package/locales/zh/translation.json +5 -1
  63. package/locales/zh-simplified/translation.json +5 -1
  64. package/package.json +2 -2
  65. package/{audio.js → src/audio.js} +1 -1
  66. package/src/autoscroll.js +189 -0
  67. package/src/input-simulator.js +518 -0
  68. package/tracky-mouse.css +33 -2
  69. package/tracky-mouse.js +166 -58
@@ -0,0 +1,189 @@
1
+
2
+ const indicator = document.createElement("div");
3
+ indicator.innerHTML = `
4
+ <svg width="32" height="32" viewBox="0 0 32 32">
5
+ <!-- base shape -->
6
+ <circle cx="16" cy="16" r="13" fill="rgb(230, 230, 230)" stroke="rgb(50, 50, 50)" stroke-width="1" />
7
+ <!-- middle dot -->
8
+ <circle cx="16" cy="16" r="2" fill="rgb(0, 0, 0)" />
9
+ <!-- triangle above -->
10
+ <polygon data-axis="y" points="16,5 13,10 19,10" fill="rgb(0, 0, 0)" />
11
+ <!-- triangle below -->
12
+ <polygon data-axis="y" points="16,27 13,22 19,22" fill="rgb(0, 0, 0)" />
13
+ <!-- triangle left -->
14
+ <polygon data-axis="x" points="5,16 10,13 10,19" fill="rgb(0, 0, 0)" />
15
+ <!-- triangle right -->
16
+ <polygon data-axis="x" points="27,16 22,13 22,19" fill="rgb(0, 0, 0)" />
17
+ </svg>
18
+ `;
19
+ indicator.style.position = "fixed";
20
+ indicator.style.pointerEvents = "none";
21
+ indicator.style.transform = "translate(-50%, -50%)";
22
+ indicator.style.zIndex = "800000"; // below .tracky-mouse-cursor and inputFeedbackCanvas
23
+
24
+ const lockingClickRadius = 10; // pixels
25
+ const scrollSpeed = 0.01;
26
+ const scrollExponent = 1.6;
27
+ const deadZone = 10; // pixels (taxicab distance)
28
+ const maxDeltaTime = 100; // milliseconds
29
+
30
+
31
+ // Block clicks with a full-page transparent element while autoscrolling,
32
+ // so it doesn't doubly-act when stopping locked autoscroll with a click.
33
+ const clickBlocker = document.createElement("div");
34
+ clickBlocker.style.position = "fixed";
35
+ clickBlocker.style.left = "0";
36
+ clickBlocker.style.top = "0";
37
+ clickBlocker.style.width = "100%";
38
+ clickBlocker.style.height = "100%";
39
+ clickBlocker.style.zIndex = "1000000";
40
+ clickBlocker.style.pointerEvents = "auto"; // default
41
+ clickBlocker.style.backgroundColor = "transparent"; // default (but could override weird CSS ig)
42
+ clickBlocker.addEventListener("pointerdown", (event) => {
43
+ event.stopPropagation();
44
+ event.preventDefault();
45
+ autoscroll.stopAutoscroll();
46
+ });
47
+
48
+ addEventListener("keydown", (event) => {
49
+ if (event.key === "Escape" && autoscroll._start) {
50
+ event.stopPropagation();
51
+ event.preventDefault();
52
+ autoscroll.stopAutoscroll();
53
+ }
54
+ }, { capture: true });
55
+
56
+ export const autoscroll = {
57
+ _start: null,
58
+ _currentScrollDelta: null,
59
+ _lastTimestamp: null,
60
+ _animationFrameRequest: null,
61
+ pointerDown(target, x, y, buttonIndex = 0, pointerId) {
62
+ if (buttonIndex !== 1) {
63
+ this.stopAutoscroll();
64
+ return;
65
+ }
66
+ if (target.closest("a")) return;
67
+ this.startAutoscroll(target, x, y, pointerId);
68
+ },
69
+ pointerUp(_target, x, y, buttonIndex = 0, _pointerId) {
70
+ // Allow any pointer to stop autoscroll, because it's more likely to be annoying if it gets stuck
71
+ if (buttonIndex !== 1 || !this._start) return;
72
+ if (Math.hypot(x - this._start.x, y - this._start.y) < lockingClickRadius) {
73
+ return; // lock autoscroll mode until next click
74
+ }
75
+ this.stopAutoscroll();
76
+ },
77
+ startAutoscroll(target, x, y, pointerId) {
78
+ indicator.style.left = `${x}px`;
79
+ indicator.style.top = `${y}px`;
80
+ document.body.appendChild(indicator);
81
+ document.body.appendChild(clickBlocker);
82
+ this._start = { x, y, target, pointerId };
83
+ this._currentScrollDelta = null;
84
+ this._lastTimestamp = performance.now();
85
+ // Update arrow visibility immediately, and start animation loop
86
+ this.updateAutoscroll();
87
+ },
88
+ stopAutoscroll() {
89
+ this._start = null;
90
+ this._currentScrollDelta = null;
91
+ this._lastTimestamp = null;
92
+ if (indicator.parentElement) {
93
+ document.body.removeChild(indicator);
94
+ }
95
+ if (clickBlocker.parentElement) {
96
+ document.body.removeChild(clickBlocker);
97
+ }
98
+ cancelAnimationFrame(this._animationFrameRequest);
99
+ this._animationFrameRequest = null;
100
+ },
101
+ pointerMove(_target, x, y, pointerId) {
102
+ // Don't allow other pointers to affect autoscroll started by a different pointer
103
+ if (!this._start || this._start.pointerId !== pointerId) return;
104
+ const diff = { x: x - this._start.x, y: y - this._start.y };
105
+ // Note: Don't return early if within deadzone,
106
+ // because we still want to update the indicator arrows.
107
+ if (Math.abs(diff.x) < deadZone) diff.x = 0;
108
+ if (Math.abs(diff.y) < deadZone) diff.y = 0;
109
+ diff.x -= Math.sign(diff.x) * deadZone;
110
+ diff.y -= Math.sign(diff.y) * deadZone;
111
+
112
+ // Note: there's a question of whether to apply the exponent or multiplier first.
113
+ // I think with exponent after multiplier, adjusting the exponent changes the
114
+ // average speed less for nominal values of input/exponent/multiplier,
115
+ // making it more intuitive to tweak the curvature,
116
+ // but tweaking the multiplier may be more intuitive, at least in a strict mathematical sense,
117
+ // with the exponent applied first.
118
+ // The set of curves expressible should be equal.
119
+ // As an aside, switching between the two orders could be easier if we used one variable
120
+ // instead of both `diff` and `scrollDelta`. I doubt it would harm clarity.
121
+ const scrollDelta = { x: diff.x * scrollSpeed, y: diff.y * scrollSpeed };
122
+ scrollDelta.x = Math.sign(scrollDelta.x) * Math.pow(Math.abs(scrollDelta.x), scrollExponent);
123
+ scrollDelta.y = Math.sign(scrollDelta.y) * Math.pow(Math.abs(scrollDelta.y), scrollExponent);
124
+ this._currentScrollDelta = scrollDelta;
125
+ },
126
+ getScrollable() {
127
+ let container = this._start.target;
128
+ let canScrollX = false;
129
+ let canScrollY = false;
130
+ while (container && container !== document.body) {
131
+ // This initial test gives a false positive on the demo section of the website
132
+ // Trying an actual scroll seems like a sure test, but could cause performance issues
133
+ canScrollX = container.scrollWidth > container.clientWidth;
134
+ canScrollY = container.scrollHeight > container.clientHeight;
135
+ if (canScrollX || canScrollY) {
136
+ if (canScrollX) {
137
+ const oldScrollLeft = container.scrollLeft;
138
+ container.scrollLeft = 1;
139
+ if (container.scrollLeft === 0) {
140
+ canScrollX = false;
141
+ }
142
+ container.scrollLeft = oldScrollLeft;
143
+ }
144
+ if (canScrollY) {
145
+ const oldScrollTop = container.scrollTop;
146
+ container.scrollTop = 1;
147
+ if (container.scrollTop === 0) {
148
+ canScrollY = false;
149
+ }
150
+ container.scrollTop = oldScrollTop;
151
+ }
152
+ }
153
+ if (canScrollX || canScrollY) {
154
+ break;
155
+ }
156
+ container = container.parentElement;
157
+ }
158
+ if (!container || container === document.body) {
159
+ // container = document.scrollingElement;
160
+ container = window;
161
+ canScrollX = document.scrollingElement.scrollWidth > document.scrollingElement.clientWidth;
162
+ canScrollY = document.scrollingElement.scrollHeight > document.scrollingElement.clientHeight;
163
+ }
164
+ return { container, canScrollX, canScrollY };
165
+ },
166
+ updateAutoscroll() {
167
+ const deltaTime = Math.min(maxDeltaTime, performance.now() - this._lastTimestamp);
168
+ // Note: we could optimize by not calling getScrollable every frame
169
+ const { container, canScrollX, canScrollY } = this.getScrollable();
170
+ const scrollDelta = this._currentScrollDelta;
171
+ if (scrollDelta) {
172
+ // Note: scrolling might be limited to integers, which could cause it to not scroll at low speeds,
173
+ // especially at high frame rates,
174
+ // and affect the accuracy of deltaTime-based movement. We could accumulate fractional scroll
175
+ // deltas and apply them when they reach a whole pixel.
176
+ container.scrollBy(scrollDelta.x * deltaTime, scrollDelta.y * deltaTime);
177
+ }
178
+
179
+ for (const arrow of indicator.querySelectorAll("[data-axis]")) {
180
+ const axis = arrow.dataset.axis;
181
+ arrow.style.display = (axis === "x" ? canScrollX : canScrollY) ? "" : "none";
182
+ }
183
+
184
+ this._lastTimestamp = performance.now();
185
+
186
+ cancelAnimationFrame(this._animationFrameRequest);
187
+ this._animationFrameRequest = requestAnimationFrame(() => this.updateAutoscroll());
188
+ },
189
+ };