@blotch/angular-lynx 22.2.5 → 22.2.7
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/fesm2022/blotch-angular-lynx-arena-Cycr_O6y.mjs +755 -0
- package/fesm2022/blotch-angular-lynx-arena-Cycr_O6y.mjs.map +1 -0
- package/fesm2022/blotch-angular-lynx-const-MkK6UdZ7.mjs +30 -0
- package/fesm2022/blotch-angular-lynx-const-MkK6UdZ7.mjs.map +1 -0
- package/fesm2022/blotch-angular-lynx-drawn-scale-ExB6Yx-p.mjs +9 -0
- package/fesm2022/blotch-angular-lynx-drawn-scale-ExB6Yx-p.mjs.map +1 -0
- package/fesm2022/{blotch-angular-lynx-web-glass-zlVeee5K.mjs → blotch-angular-lynx-web-glass-Bmp-vSYh.mjs} +2 -7
- package/fesm2022/blotch-angular-lynx-web-glass-Bmp-vSYh.mjs.map +1 -0
- package/fesm2022/blotch-angular-lynx.mjs +4051 -3800
- package/fesm2022/blotch-angular-lynx.mjs.map +1 -1
- package/package.json +1 -1
- package/schematics/ng-add/index.js +7 -3
- package/schematics/utility/pnpm-builds.js +210 -0
- package/types/blotch-angular-lynx.d.ts +214 -3
- package/fesm2022/blotch-angular-lynx-web-glass-zlVeee5K.mjs.map +0 -1
|
@@ -0,0 +1,755 @@
|
|
|
1
|
+
import { r as GestureType } from "./blotch-angular-lynx-const-MkK6UdZ7.mjs";
|
|
2
|
+
import { t as drawnScale } from "./blotch-angular-lynx-drawn-scale-ExB6Yx-p.mjs";
|
|
3
|
+
const ORIGIN = {
|
|
4
|
+
x: 0,
|
|
5
|
+
y: 0
|
|
6
|
+
};
|
|
7
|
+
const pageOf = (element) => {
|
|
8
|
+
return element.getRootNode().host ?? element.ownerDocument.documentElement;
|
|
9
|
+
};
|
|
10
|
+
const touchPointOf = (event, type, target) => {
|
|
11
|
+
const page = pageOf(target);
|
|
12
|
+
const scale = drawnScale(page);
|
|
13
|
+
const pageBox = page.getBoundingClientRect();
|
|
14
|
+
const box = target.getBoundingClientRect();
|
|
15
|
+
return {
|
|
16
|
+
type,
|
|
17
|
+
timestamp: event.timeStamp,
|
|
18
|
+
x: (event.clientX - box.left) / scale,
|
|
19
|
+
y: (event.clientY - box.top) / scale,
|
|
20
|
+
pageX: (event.clientX - pageBox.left) / scale,
|
|
21
|
+
pageY: (event.clientY - pageBox.top) / scale,
|
|
22
|
+
clientX: event.clientX,
|
|
23
|
+
clientY: event.clientY
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
const VELOCITY_WINDOW = 100;
|
|
27
|
+
var VelocityTracker = class {
|
|
28
|
+
#samples = [];
|
|
29
|
+
reset() {
|
|
30
|
+
this.#samples = [];
|
|
31
|
+
}
|
|
32
|
+
add(touch) {
|
|
33
|
+
const t = touch.timestamp;
|
|
34
|
+
this.#samples.push({
|
|
35
|
+
t,
|
|
36
|
+
x: touch.pageX,
|
|
37
|
+
y: touch.pageY
|
|
38
|
+
});
|
|
39
|
+
this.#samples = this.#samples.filter((sample) => t - sample.t <= VELOCITY_WINDOW);
|
|
40
|
+
}
|
|
41
|
+
velocity() {
|
|
42
|
+
const first = this.#samples[0];
|
|
43
|
+
const last = this.#samples[this.#samples.length - 1];
|
|
44
|
+
const seconds = first ? (last.t - first.t) / 1e3 : 0;
|
|
45
|
+
if (seconds <= 0) return ORIGIN;
|
|
46
|
+
return {
|
|
47
|
+
x: (last.x - first.x) / seconds,
|
|
48
|
+
y: (last.y - first.y) / seconds
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
const MIN_VELOCITY = 50;
|
|
53
|
+
const MAX_VELOCITY = 1e4;
|
|
54
|
+
const DECELERATION_RATE = .998;
|
|
55
|
+
const COEFFICIENT = 1e3 * Math.log(DECELERATION_RATE);
|
|
56
|
+
const distanceAt = (seconds, duration, velocity) => {
|
|
57
|
+
const progress = Math.min(1, seconds / duration);
|
|
58
|
+
return (DECELERATION_RATE ** (1e3 * progress * duration) - 1) / COEFFICIENT * velocity;
|
|
59
|
+
};
|
|
60
|
+
var FlingTrigger = class {
|
|
61
|
+
state = "end";
|
|
62
|
+
distance = ORIGIN;
|
|
63
|
+
lastDistance = ORIGIN;
|
|
64
|
+
#onFrame;
|
|
65
|
+
#frames = null;
|
|
66
|
+
#frame;
|
|
67
|
+
#running = false;
|
|
68
|
+
#begin = 0;
|
|
69
|
+
#velocity = ORIGIN;
|
|
70
|
+
#flingX = false;
|
|
71
|
+
#flingY = false;
|
|
72
|
+
#durationX = 0;
|
|
73
|
+
#durationY = 0;
|
|
74
|
+
constructor(onFrame) {
|
|
75
|
+
this.#onFrame = onFrame;
|
|
76
|
+
}
|
|
77
|
+
start(velocity, frames) {
|
|
78
|
+
const clamp = (v) => Math.max(Math.min(MAX_VELOCITY, v), -1e4);
|
|
79
|
+
const v = {
|
|
80
|
+
x: clamp(velocity.x),
|
|
81
|
+
y: clamp(velocity.y)
|
|
82
|
+
};
|
|
83
|
+
const flingX = Math.abs(v.x) >= MIN_VELOCITY;
|
|
84
|
+
const flingY = Math.abs(v.y) >= MIN_VELOCITY;
|
|
85
|
+
if (!flingX && !flingY) return false;
|
|
86
|
+
this.stop();
|
|
87
|
+
const threshold = .5 / (frames.devicePixelRatio || 1);
|
|
88
|
+
const duration = (speed) => Math.log(-COEFFICIENT * threshold / Math.abs(speed)) / COEFFICIENT;
|
|
89
|
+
this.#frames = frames;
|
|
90
|
+
this.#velocity = v;
|
|
91
|
+
this.#flingX = flingX;
|
|
92
|
+
this.#flingY = flingY;
|
|
93
|
+
this.#durationX = duration(v.x);
|
|
94
|
+
this.#durationY = duration(v.y);
|
|
95
|
+
this.#begin = frames.performance.now();
|
|
96
|
+
this.distance = ORIGIN;
|
|
97
|
+
this.lastDistance = ORIGIN;
|
|
98
|
+
this.state = "start";
|
|
99
|
+
this.#running = true;
|
|
100
|
+
this.#frame = frames.requestAnimationFrame(this.#tick);
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
stop() {
|
|
104
|
+
this.#running = false;
|
|
105
|
+
if (this.#frame !== void 0) this.#frames?.cancelAnimationFrame(this.#frame);
|
|
106
|
+
this.#frame = void 0;
|
|
107
|
+
}
|
|
108
|
+
reset() {
|
|
109
|
+
this.stop();
|
|
110
|
+
this.distance = ORIGIN;
|
|
111
|
+
this.lastDistance = ORIGIN;
|
|
112
|
+
this.state = "end";
|
|
113
|
+
}
|
|
114
|
+
isFinished() {
|
|
115
|
+
return !this.#running;
|
|
116
|
+
}
|
|
117
|
+
#tick = (now) => {
|
|
118
|
+
this.#frame = void 0;
|
|
119
|
+
if (this.state === "start") {
|
|
120
|
+
this.#onFrame(this);
|
|
121
|
+
if (!this.#running) return;
|
|
122
|
+
this.state = "update";
|
|
123
|
+
}
|
|
124
|
+
const seconds = Math.max(0, now - this.#begin) / 1e3;
|
|
125
|
+
const done = (fling, duration) => !fling || seconds >= duration;
|
|
126
|
+
const willEnd = done(this.#flingX, this.#durationX) && done(this.#flingY, this.#durationY);
|
|
127
|
+
this.distance = {
|
|
128
|
+
x: this.#flingX ? distanceAt(seconds, this.#durationX, this.#velocity.x) : this.lastDistance.x,
|
|
129
|
+
y: this.#flingY ? distanceAt(seconds, this.#durationY, this.#velocity.y) : this.lastDistance.y
|
|
130
|
+
};
|
|
131
|
+
this.#onFrame(this);
|
|
132
|
+
if (!this.#running) return;
|
|
133
|
+
this.lastDistance = this.distance;
|
|
134
|
+
if (willEnd) {
|
|
135
|
+
this.state = "end";
|
|
136
|
+
this.#onFrame(this);
|
|
137
|
+
this.stop();
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
this.#frame = this.#frames.requestAnimationFrame(this.#tick);
|
|
141
|
+
};
|
|
142
|
+
};
|
|
143
|
+
const HandlerState = {
|
|
144
|
+
Init: 0,
|
|
145
|
+
Begin: 1,
|
|
146
|
+
Active: 2,
|
|
147
|
+
Fail: 3,
|
|
148
|
+
Cancel: 4,
|
|
149
|
+
End: 5,
|
|
150
|
+
Undetermined: 6
|
|
151
|
+
};
|
|
152
|
+
const FLING_END = {
|
|
153
|
+
x: Number.EPSILON,
|
|
154
|
+
y: Number.EPSILON
|
|
155
|
+
};
|
|
156
|
+
const option = (config, key, fallback) => config ? Number(config[key]) || 0 : fallback;
|
|
157
|
+
const touchParams = (touch) => touch ? {
|
|
158
|
+
timestamp: touch.timestamp,
|
|
159
|
+
type: touch.type,
|
|
160
|
+
x: touch.x,
|
|
161
|
+
y: touch.y,
|
|
162
|
+
pageX: touch.pageX,
|
|
163
|
+
pageY: touch.pageY,
|
|
164
|
+
clientX: touch.clientX,
|
|
165
|
+
clientY: touch.clientY
|
|
166
|
+
} : {};
|
|
167
|
+
const SCROLL_PARAMS = {
|
|
168
|
+
scrollX: 0,
|
|
169
|
+
scrollY: 0,
|
|
170
|
+
isAtStart: false,
|
|
171
|
+
isAtEnd: false
|
|
172
|
+
};
|
|
173
|
+
const pagePoint = (touch) => ({
|
|
174
|
+
x: touch.pageX,
|
|
175
|
+
y: touch.pageY
|
|
176
|
+
});
|
|
177
|
+
const beyond = (from, to, distance) => Math.abs(to.x - from.x) > distance || Math.abs(to.y - from.y) > distance;
|
|
178
|
+
var WebGestureHandler = class {
|
|
179
|
+
detector;
|
|
180
|
+
status = HandlerState.Init;
|
|
181
|
+
#emit;
|
|
182
|
+
constructor(detector, emit) {
|
|
183
|
+
this.detector = detector;
|
|
184
|
+
this.#emit = emit;
|
|
185
|
+
}
|
|
186
|
+
dispose() {}
|
|
187
|
+
reset() {
|
|
188
|
+
this.status = HandlerState.Init;
|
|
189
|
+
}
|
|
190
|
+
begin() {
|
|
191
|
+
this.status = HandlerState.Begin;
|
|
192
|
+
}
|
|
193
|
+
activate() {
|
|
194
|
+
this.status = HandlerState.Active;
|
|
195
|
+
}
|
|
196
|
+
fail() {
|
|
197
|
+
if (this.status !== HandlerState.End) this.status = HandlerState.Cancel;
|
|
198
|
+
}
|
|
199
|
+
end() {
|
|
200
|
+
this.status = HandlerState.End;
|
|
201
|
+
}
|
|
202
|
+
ignore() {
|
|
203
|
+
this.status = HandlerState.Undetermined;
|
|
204
|
+
}
|
|
205
|
+
touches(type, touch) {
|
|
206
|
+
this.send({
|
|
207
|
+
touchstart: "onTouchesDown",
|
|
208
|
+
touchmove: "onTouchesMove",
|
|
209
|
+
touchend: "onTouchesUp",
|
|
210
|
+
touchcancel: "onTouchesCancel"
|
|
211
|
+
}[type], touchParams(touch));
|
|
212
|
+
}
|
|
213
|
+
send(name, params) {
|
|
214
|
+
if (this.detector.callbacks.has(name)) this.#emit(this.detector, name, params);
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
var PanHandler = class extends WebGestureHandler {
|
|
218
|
+
#minDistance = option(this.detector.config, "minDistance", 0);
|
|
219
|
+
#start = ORIGIN;
|
|
220
|
+
#last = ORIGIN;
|
|
221
|
+
#lastTouch = null;
|
|
222
|
+
#begun = false;
|
|
223
|
+
#started = false;
|
|
224
|
+
#ended = false;
|
|
225
|
+
handle(type, touch) {
|
|
226
|
+
this.#lastTouch = touch;
|
|
227
|
+
if (!touch) {
|
|
228
|
+
this.ignore();
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
if (this.status >= HandlerState.Fail) return;
|
|
232
|
+
if (type === "touchstart") {
|
|
233
|
+
this.#start = pagePoint(touch);
|
|
234
|
+
this.#ended = false;
|
|
235
|
+
this.begin();
|
|
236
|
+
this.#onBegin(touch);
|
|
237
|
+
} else if (type === "touchmove") {
|
|
238
|
+
this.#last = pagePoint(touch);
|
|
239
|
+
if (this.status === HandlerState.Init) {
|
|
240
|
+
this.begin();
|
|
241
|
+
this.#onBegin(touch);
|
|
242
|
+
}
|
|
243
|
+
if (beyond(this.#start, this.#last, this.#minDistance)) {
|
|
244
|
+
this.activate();
|
|
245
|
+
this.#onStart(touch);
|
|
246
|
+
}
|
|
247
|
+
if (this.status === HandlerState.Active) this.send("onUpdate", {
|
|
248
|
+
...SCROLL_PARAMS,
|
|
249
|
+
...touchParams(touch)
|
|
250
|
+
});
|
|
251
|
+
} else this.fail();
|
|
252
|
+
}
|
|
253
|
+
fail() {
|
|
254
|
+
super.fail();
|
|
255
|
+
this.#onEnd();
|
|
256
|
+
}
|
|
257
|
+
end() {
|
|
258
|
+
super.end();
|
|
259
|
+
this.#onEnd();
|
|
260
|
+
}
|
|
261
|
+
reset() {
|
|
262
|
+
super.reset();
|
|
263
|
+
this.#begun = false;
|
|
264
|
+
this.#started = false;
|
|
265
|
+
this.#ended = false;
|
|
266
|
+
}
|
|
267
|
+
#onBegin(touch) {
|
|
268
|
+
if (this.#begun) return;
|
|
269
|
+
this.#begun = true;
|
|
270
|
+
this.send("onBegin", {
|
|
271
|
+
...SCROLL_PARAMS,
|
|
272
|
+
...touchParams(touch)
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
#onStart(touch) {
|
|
276
|
+
if (this.#started || !this.#begun) return;
|
|
277
|
+
this.#started = true;
|
|
278
|
+
this.send("onStart", {
|
|
279
|
+
...SCROLL_PARAMS,
|
|
280
|
+
...touchParams(touch)
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
#onEnd() {
|
|
284
|
+
if (this.#ended || !this.#begun) return;
|
|
285
|
+
this.#ended = true;
|
|
286
|
+
this.send("onEnd", {
|
|
287
|
+
...SCROLL_PARAMS,
|
|
288
|
+
...touchParams(this.#lastTouch)
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
var TapHandler = class extends WebGestureHandler {
|
|
293
|
+
#maxDuration = option(this.detector.config, "maxDuration", 500);
|
|
294
|
+
#maxDistance = option(this.detector.config, "maxDistance", 10);
|
|
295
|
+
#start = ORIGIN;
|
|
296
|
+
#lastTouch = null;
|
|
297
|
+
#timer;
|
|
298
|
+
handle(type, touch) {
|
|
299
|
+
this.#lastTouch = touch;
|
|
300
|
+
if (!touch) {
|
|
301
|
+
this.ignore();
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
if (this.status >= HandlerState.Fail) {
|
|
305
|
+
this.dispose();
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
if (type === "touchstart") {
|
|
309
|
+
this.#start = pagePoint(touch);
|
|
310
|
+
this.begin();
|
|
311
|
+
this.send("onBegin", touchParams(touch));
|
|
312
|
+
this.#startTimer();
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
if (type === "touchmove") {
|
|
316
|
+
if (beyond(this.#start, pagePoint(touch), this.#maxDistance)) this.fail();
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
if (type === "touchcancel") this.fail();
|
|
320
|
+
else {
|
|
321
|
+
this.activate();
|
|
322
|
+
this.send("onStart", touchParams(touch));
|
|
323
|
+
this.send("onEnd", touchParams(touch));
|
|
324
|
+
}
|
|
325
|
+
this.dispose();
|
|
326
|
+
}
|
|
327
|
+
dispose() {
|
|
328
|
+
if (this.#timer !== void 0) clearTimeout(this.#timer);
|
|
329
|
+
this.#timer = void 0;
|
|
330
|
+
}
|
|
331
|
+
fail() {
|
|
332
|
+
super.fail();
|
|
333
|
+
this.send("onEnd", touchParams(this.#lastTouch));
|
|
334
|
+
}
|
|
335
|
+
end() {
|
|
336
|
+
super.end();
|
|
337
|
+
this.send("onEnd", touchParams(this.#lastTouch));
|
|
338
|
+
}
|
|
339
|
+
#startTimer() {
|
|
340
|
+
this.dispose();
|
|
341
|
+
this.#timer = setTimeout(() => {
|
|
342
|
+
this.#timer = void 0;
|
|
343
|
+
this.fail();
|
|
344
|
+
}, this.#maxDuration);
|
|
345
|
+
}
|
|
346
|
+
};
|
|
347
|
+
var LongPressHandler = class extends WebGestureHandler {
|
|
348
|
+
#minDuration = option(this.detector.config, "minDuration", 500);
|
|
349
|
+
#maxDistance = option(this.detector.config, "maxDistance", 10);
|
|
350
|
+
#start = ORIGIN;
|
|
351
|
+
#lastTouch = null;
|
|
352
|
+
#timer;
|
|
353
|
+
handle(type, touch) {
|
|
354
|
+
this.#lastTouch = touch;
|
|
355
|
+
if (!touch) {
|
|
356
|
+
this.ignore();
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
if (this.status >= HandlerState.Fail) {
|
|
360
|
+
this.dispose();
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
if (type === "touchstart") {
|
|
364
|
+
this.#start = pagePoint(touch);
|
|
365
|
+
this.begin();
|
|
366
|
+
this.send("onBegin", touchParams(touch));
|
|
367
|
+
this.#startTimer();
|
|
368
|
+
} else if (type === "touchmove") {
|
|
369
|
+
if (this.status === HandlerState.Begin && beyond(this.#start, pagePoint(touch), this.#maxDistance)) {
|
|
370
|
+
this.fail();
|
|
371
|
+
this.dispose();
|
|
372
|
+
}
|
|
373
|
+
} else {
|
|
374
|
+
this.dispose();
|
|
375
|
+
this.fail();
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
dispose() {
|
|
379
|
+
if (this.#timer !== void 0) clearTimeout(this.#timer);
|
|
380
|
+
this.#timer = void 0;
|
|
381
|
+
}
|
|
382
|
+
fail() {
|
|
383
|
+
super.fail();
|
|
384
|
+
this.send("onEnd", touchParams(this.#lastTouch));
|
|
385
|
+
}
|
|
386
|
+
end() {
|
|
387
|
+
super.end();
|
|
388
|
+
this.send("onEnd", touchParams(this.#lastTouch));
|
|
389
|
+
}
|
|
390
|
+
#startTimer() {
|
|
391
|
+
this.dispose();
|
|
392
|
+
this.#timer = setTimeout(() => {
|
|
393
|
+
this.#timer = void 0;
|
|
394
|
+
if (this.status !== HandlerState.Begin) return;
|
|
395
|
+
this.activate();
|
|
396
|
+
this.send("onStart", touchParams(this.#lastTouch));
|
|
397
|
+
}, this.#minDuration);
|
|
398
|
+
}
|
|
399
|
+
};
|
|
400
|
+
var FlingHandler = class extends WebGestureHandler {
|
|
401
|
+
#begun = false;
|
|
402
|
+
#started = false;
|
|
403
|
+
#ended = false;
|
|
404
|
+
handle(type, touch, step) {
|
|
405
|
+
if (touch) {
|
|
406
|
+
if (type === "touchend") {
|
|
407
|
+
this.begin();
|
|
408
|
+
this.#onBegin(ORIGIN);
|
|
409
|
+
} else this.ignore();
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
if (this.status >= HandlerState.Fail && this.status <= HandlerState.End) {
|
|
413
|
+
this.#onEnd(ORIGIN);
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
if (step === FLING_END) {
|
|
417
|
+
this.fail();
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
if (this.status === HandlerState.Init || this.status === HandlerState.Undetermined) {
|
|
421
|
+
this.begin();
|
|
422
|
+
this.activate();
|
|
423
|
+
this.#onBegin(ORIGIN);
|
|
424
|
+
this.#onStart(ORIGIN);
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
this.send("onUpdate", this.#params(step));
|
|
428
|
+
}
|
|
429
|
+
fail() {
|
|
430
|
+
super.fail();
|
|
431
|
+
this.#onEnd(ORIGIN);
|
|
432
|
+
}
|
|
433
|
+
end() {
|
|
434
|
+
super.end();
|
|
435
|
+
this.#onEnd(ORIGIN);
|
|
436
|
+
}
|
|
437
|
+
reset() {
|
|
438
|
+
super.reset();
|
|
439
|
+
this.#begun = false;
|
|
440
|
+
this.#started = false;
|
|
441
|
+
this.#ended = false;
|
|
442
|
+
}
|
|
443
|
+
#onBegin(step) {
|
|
444
|
+
if (this.#begun || !this.detector.callbacks.has("onBegin")) return;
|
|
445
|
+
this.#begun = true;
|
|
446
|
+
this.send("onBegin", this.#params(step));
|
|
447
|
+
}
|
|
448
|
+
#onStart(step) {
|
|
449
|
+
if (this.#started || !this.#begun) return;
|
|
450
|
+
this.#started = true;
|
|
451
|
+
this.send("onStart", this.#params(step));
|
|
452
|
+
}
|
|
453
|
+
#onEnd(step) {
|
|
454
|
+
if (this.#ended || !this.#begun) return;
|
|
455
|
+
this.#ended = true;
|
|
456
|
+
this.send("onEnd", this.#params(step));
|
|
457
|
+
}
|
|
458
|
+
#params(step) {
|
|
459
|
+
return {
|
|
460
|
+
...SCROLL_PARAMS,
|
|
461
|
+
deltaX: step.x,
|
|
462
|
+
deltaY: step.y
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
};
|
|
466
|
+
const createHandlers = (detectors, emit) => {
|
|
467
|
+
const handlers = [
|
|
468
|
+
[GestureType.PAN, PanHandler],
|
|
469
|
+
[GestureType.FLING, FlingHandler],
|
|
470
|
+
[GestureType.TAP, TapHandler],
|
|
471
|
+
[GestureType.LONGPRESS, LongPressHandler],
|
|
472
|
+
[GestureType.NATIVE, PanHandler]
|
|
473
|
+
];
|
|
474
|
+
const all = [...detectors];
|
|
475
|
+
return handlers.flatMap(([type, Handler]) => all.filter((detector) => detector.type === type).map((detector) => new Handler(detector, emit)));
|
|
476
|
+
};
|
|
477
|
+
const FAIL_STATE = 2;
|
|
478
|
+
const END_STATE = 3;
|
|
479
|
+
const POINTER_EVENTS = [
|
|
480
|
+
"pointermove",
|
|
481
|
+
"pointerup",
|
|
482
|
+
"pointercancel"
|
|
483
|
+
];
|
|
484
|
+
const DRAG_EVENTS = ["selectstart", "dragstart"];
|
|
485
|
+
var WebGestureArena = class {
|
|
486
|
+
#afterDispatch;
|
|
487
|
+
#members = /* @__PURE__ */ new Map();
|
|
488
|
+
#gestureMembers = /* @__PURE__ */ new Map();
|
|
489
|
+
#velocity = new VelocityTracker();
|
|
490
|
+
#flinger = new FlingTrigger(() => this.#onFling());
|
|
491
|
+
#pointer = null;
|
|
492
|
+
#bubble = [];
|
|
493
|
+
#chain = [];
|
|
494
|
+
#winner = null;
|
|
495
|
+
#lastWinner = null;
|
|
496
|
+
#lastFlingWinner = null;
|
|
497
|
+
#simultaneousMembers = /* @__PURE__ */ new Set();
|
|
498
|
+
#simultaneousIds = /* @__PURE__ */ new Set();
|
|
499
|
+
constructor(afterDispatch) {
|
|
500
|
+
this.#afterDispatch = afterDispatch;
|
|
501
|
+
}
|
|
502
|
+
setDetector(node, id, type, config, relations) {
|
|
503
|
+
let member = this.#members.get(node);
|
|
504
|
+
if (!member) {
|
|
505
|
+
const element = node;
|
|
506
|
+
member = {
|
|
507
|
+
element,
|
|
508
|
+
detectors: /* @__PURE__ */ new Map(),
|
|
509
|
+
handlers: null
|
|
510
|
+
};
|
|
511
|
+
this.#members.set(node, member);
|
|
512
|
+
element.addEventListener("pointerdown", this.#onPointerDown);
|
|
513
|
+
element.addEventListener("touchmove", this.#onTouchMove, { passive: false });
|
|
514
|
+
}
|
|
515
|
+
member.detectors.set(id, {
|
|
516
|
+
id,
|
|
517
|
+
type,
|
|
518
|
+
config: config.config,
|
|
519
|
+
callbacks: new Map(config.callbacks.map(({ name, callback }) => [name, callback])),
|
|
520
|
+
waitFor: relations["waitFor"] ?? [],
|
|
521
|
+
simultaneous: relations["simultaneous"] ?? [],
|
|
522
|
+
continueWith: relations["continueWith"] ?? []
|
|
523
|
+
});
|
|
524
|
+
this.#invalidate(member);
|
|
525
|
+
let members = this.#gestureMembers.get(id);
|
|
526
|
+
if (!members) {
|
|
527
|
+
members = /* @__PURE__ */ new Set();
|
|
528
|
+
this.#gestureMembers.set(id, members);
|
|
529
|
+
}
|
|
530
|
+
members.add(member);
|
|
531
|
+
}
|
|
532
|
+
removeDetector(node, id) {
|
|
533
|
+
const member = this.#members.get(node);
|
|
534
|
+
if (!member?.detectors.delete(id)) return;
|
|
535
|
+
this.#invalidate(member);
|
|
536
|
+
const members = this.#gestureMembers.get(id);
|
|
537
|
+
members.delete(member);
|
|
538
|
+
if (!members.size) this.#gestureMembers.delete(id);
|
|
539
|
+
if (member.detectors.size) return;
|
|
540
|
+
this.#members.delete(node);
|
|
541
|
+
member.element.removeEventListener("pointerdown", this.#onPointerDown);
|
|
542
|
+
member.element.removeEventListener("touchmove", this.#onTouchMove);
|
|
543
|
+
}
|
|
544
|
+
setState(node, id, state) {
|
|
545
|
+
const handler = this.#members.get(node)?.handlers?.find((other) => other.detector.id === id);
|
|
546
|
+
if (state === FAIL_STATE) handler?.fail();
|
|
547
|
+
else if (state === END_STATE) handler?.end();
|
|
548
|
+
}
|
|
549
|
+
#invalidate(member) {
|
|
550
|
+
for (const handler of member.handlers ?? []) handler.dispose();
|
|
551
|
+
member.handlers = null;
|
|
552
|
+
}
|
|
553
|
+
#handlersOf(member) {
|
|
554
|
+
member.handlers ??= createHandlers(member.detectors.values(), this.#emit);
|
|
555
|
+
return member.handlers;
|
|
556
|
+
}
|
|
557
|
+
#emit = (detector, name, params) => {
|
|
558
|
+
const callback = detector.callbacks.get(name);
|
|
559
|
+
try {
|
|
560
|
+
callback._fn?.({
|
|
561
|
+
type: name,
|
|
562
|
+
timestamp: Date.now(),
|
|
563
|
+
params
|
|
564
|
+
});
|
|
565
|
+
} catch (error) {
|
|
566
|
+
queueMicrotask(() => {
|
|
567
|
+
throw error;
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
this.#afterDispatch();
|
|
571
|
+
};
|
|
572
|
+
#onPointerDown = (event) => {
|
|
573
|
+
if (this.#pointer || event.button > 0) return;
|
|
574
|
+
const bubble = [...new Set(event.composedPath().map((node) => this.#members.get(node)).filter((member) => member !== void 0))];
|
|
575
|
+
const target = event.target;
|
|
576
|
+
const { ownerDocument } = target;
|
|
577
|
+
this.#pointer = {
|
|
578
|
+
id: event.pointerId,
|
|
579
|
+
target,
|
|
580
|
+
document: ownerDocument
|
|
581
|
+
};
|
|
582
|
+
for (const type of POINTER_EVENTS) ownerDocument.addEventListener(type, this.#onPointer, true);
|
|
583
|
+
for (const type of DRAG_EVENTS) ownerDocument.addEventListener(type, this.#onDrag, true);
|
|
584
|
+
this.#flinger.stop();
|
|
585
|
+
this.#bubble = bubble;
|
|
586
|
+
this.#chain = this.#competeChain(bubble);
|
|
587
|
+
const [winner] = this.#chain;
|
|
588
|
+
this.#winner = winner;
|
|
589
|
+
this.#lastWinner = winner;
|
|
590
|
+
this.#updateSimultaneous(winner);
|
|
591
|
+
this.#velocity.reset();
|
|
592
|
+
this.#touch(event, "touchstart");
|
|
593
|
+
};
|
|
594
|
+
#onPointer = (domEvent) => {
|
|
595
|
+
const event = domEvent;
|
|
596
|
+
if (event.pointerId !== this.#pointer?.id) return;
|
|
597
|
+
if (event.type === "pointermove") {
|
|
598
|
+
this.#touch(event, "touchmove");
|
|
599
|
+
return;
|
|
600
|
+
}
|
|
601
|
+
const { document } = this.#pointer;
|
|
602
|
+
for (const type of POINTER_EVENTS) document.removeEventListener(type, this.#onPointer, true);
|
|
603
|
+
for (const type of DRAG_EVENTS) document.removeEventListener(type, this.#onDrag, true);
|
|
604
|
+
try {
|
|
605
|
+
this.#touch(event, event.type === "pointerup" ? "touchend" : "touchcancel");
|
|
606
|
+
} finally {
|
|
607
|
+
this.#pointer = null;
|
|
608
|
+
}
|
|
609
|
+
};
|
|
610
|
+
#onTouchMove = (event) => {
|
|
611
|
+
if (this.#pointer && event.cancelable && this.#panning()) event.preventDefault();
|
|
612
|
+
};
|
|
613
|
+
#onDrag = (event) => {
|
|
614
|
+
if (this.#panning()) event.preventDefault();
|
|
615
|
+
};
|
|
616
|
+
#panning() {
|
|
617
|
+
return [...this.#chain, ...this.#simultaneousMembers].some((member) => this.#handlersOf(member).some((handler) => handler.detector.type === GestureType.PAN && handler.status < HandlerState.Fail));
|
|
618
|
+
}
|
|
619
|
+
#touch(event, type) {
|
|
620
|
+
const touch = touchPointOf(event, type, this.#pointer.target);
|
|
621
|
+
this.#velocity.add(touch);
|
|
622
|
+
if (this.#winner) for (const member of this.#bubble) for (const handler of this.#handlersOf(member)) handler.touches(type, touch);
|
|
623
|
+
this.#resolve(type, touch);
|
|
624
|
+
}
|
|
625
|
+
#resolve(type, touch) {
|
|
626
|
+
if (type === "touchstart") {
|
|
627
|
+
for (const member of this.#chain) this.#reset(member);
|
|
628
|
+
this.#dispatch(type, touch, this.#winner, ORIGIN, true);
|
|
629
|
+
this.#findNextWinner(type, touch);
|
|
630
|
+
return;
|
|
631
|
+
}
|
|
632
|
+
if (type === "touchmove") {
|
|
633
|
+
this.#winner = this.#reCompete(this.#winner);
|
|
634
|
+
if (this.#winner === this.#lastWinner) this.#dispatch(type, touch, this.#winner, ORIGIN, false);
|
|
635
|
+
this.#findNextWinner(type, touch);
|
|
636
|
+
return;
|
|
637
|
+
}
|
|
638
|
+
this.#dispatch(type, touch, this.#winner, ORIGIN, true);
|
|
639
|
+
const velocity = type === "touchend" ? this.#velocity.velocity() : ORIGIN;
|
|
640
|
+
const view = this.#pointer.document.defaultView;
|
|
641
|
+
if (this.#winner && this.#flinger.start(velocity, view)) {
|
|
642
|
+
this.#lastFlingWinner = this.#lastWinner;
|
|
643
|
+
return;
|
|
644
|
+
}
|
|
645
|
+
this.#flinger.reset();
|
|
646
|
+
this.#dispatch(null, null, this.#winner, FLING_END, true);
|
|
647
|
+
if (this.#winner) this.#onFling();
|
|
648
|
+
}
|
|
649
|
+
#onFling() {
|
|
650
|
+
const { distance, lastDistance, state } = this.#flinger;
|
|
651
|
+
const step = {
|
|
652
|
+
x: lastDistance.x - distance.x,
|
|
653
|
+
y: lastDistance.y - distance.y
|
|
654
|
+
};
|
|
655
|
+
this.#lastFlingWinner = this.#reCompete(this.#lastFlingWinner);
|
|
656
|
+
this.#findNextWinner(null, null);
|
|
657
|
+
if (!this.#winner || !this.#lastFlingWinner) {
|
|
658
|
+
this.#lastFlingWinner = null;
|
|
659
|
+
this.#flinger.stop();
|
|
660
|
+
return;
|
|
661
|
+
}
|
|
662
|
+
if (state === "end") this.#dispatch(null, null, this.#lastFlingWinner, FLING_END, true);
|
|
663
|
+
else this.#dispatch(null, null, this.#lastFlingWinner, step, false);
|
|
664
|
+
}
|
|
665
|
+
#dispatch(type, touch, member, step, reCompete) {
|
|
666
|
+
if (!member) return;
|
|
667
|
+
for (const handler of this.#handlersOf(member)) handler.handle(type, touch, step);
|
|
668
|
+
for (const other of this.#simultaneousMembers) for (const handler of this.#handlersOf(other)) handler.handle(type, touch, step);
|
|
669
|
+
if (reCompete) this.#winner = this.#reCompete(this.#winner);
|
|
670
|
+
}
|
|
671
|
+
#findNextWinner(type, touch) {
|
|
672
|
+
for (let i = 0; i < this.#chain.length; i++) {
|
|
673
|
+
if (this.#winner === this.#lastWinner || !this.#winner) return;
|
|
674
|
+
this.#lastWinner = this.#winner;
|
|
675
|
+
this.#updateSimultaneous(this.#winner);
|
|
676
|
+
this.#dispatch(type, touch, this.#winner, ORIGIN, true);
|
|
677
|
+
}
|
|
678
|
+
this.#dispatch(type, touch, this.#lastWinner, ORIGIN, true);
|
|
679
|
+
}
|
|
680
|
+
#reCompete(current) {
|
|
681
|
+
if (!current && !this.#lastWinner) return null;
|
|
682
|
+
let lost = false;
|
|
683
|
+
if (!current) {
|
|
684
|
+
current = this.#lastWinner;
|
|
685
|
+
lost = true;
|
|
686
|
+
this.#resetWithSimultaneous(current);
|
|
687
|
+
}
|
|
688
|
+
const state = this.#stateOf(current);
|
|
689
|
+
if (state <= HandlerState.Active) return current;
|
|
690
|
+
if (state === HandlerState.End || lost) return null;
|
|
691
|
+
const index = this.#chain.indexOf(current);
|
|
692
|
+
return [...this.#chain.slice(index + 1), ...this.#chain.slice(0, index)].find((member) => {
|
|
693
|
+
this.#stateOf(member);
|
|
694
|
+
this.#resetWithSimultaneous(member);
|
|
695
|
+
return this.#stateOf(member) <= HandlerState.Active;
|
|
696
|
+
}) ?? null;
|
|
697
|
+
}
|
|
698
|
+
#stateOf(member) {
|
|
699
|
+
const handlers = this.#handlersOf(member);
|
|
700
|
+
if (!handlers.length) return HandlerState.Fail;
|
|
701
|
+
let least = HandlerState.Undetermined;
|
|
702
|
+
for (const handler of handlers) {
|
|
703
|
+
if (handler.status === HandlerState.End) {
|
|
704
|
+
this.#resetWithSimultaneous(member);
|
|
705
|
+
this.#lastWinner = null;
|
|
706
|
+
return HandlerState.End;
|
|
707
|
+
}
|
|
708
|
+
if (handler.status === HandlerState.Active) {
|
|
709
|
+
for (const other of handlers) if (other !== handler && !this.#simultaneousIds.has(other.detector.id)) other.fail();
|
|
710
|
+
return HandlerState.Active;
|
|
711
|
+
}
|
|
712
|
+
least = Math.min(least, handler.status);
|
|
713
|
+
}
|
|
714
|
+
return least;
|
|
715
|
+
}
|
|
716
|
+
#reset(member) {
|
|
717
|
+
for (const handler of this.#handlersOf(member)) handler.reset();
|
|
718
|
+
}
|
|
719
|
+
#resetWithSimultaneous(member) {
|
|
720
|
+
this.#reset(member);
|
|
721
|
+
for (const other of this.#simultaneousMembers) this.#reset(other);
|
|
722
|
+
}
|
|
723
|
+
#competeChain(bubble) {
|
|
724
|
+
const chain = [];
|
|
725
|
+
for (const [index, member] of bubble.entries()) {
|
|
726
|
+
const related = [...member.detectors.values()].sort((a, b) => a.id - b.id).find((detector) => detector.waitFor.length + detector.continueWith.length);
|
|
727
|
+
const ahead = related ? this.#membersOf(related.waitFor).filter((other) => bubble.slice(index + 1).includes(other)) : [];
|
|
728
|
+
chain.push(...ahead, member);
|
|
729
|
+
if (related?.waitFor.length && !ahead.length) continue;
|
|
730
|
+
if (related?.continueWith.length) {
|
|
731
|
+
chain.push(...this.#membersOf(related.continueWith));
|
|
732
|
+
break;
|
|
733
|
+
}
|
|
734
|
+
if (ahead.length) break;
|
|
735
|
+
}
|
|
736
|
+
return [...new Set(chain)];
|
|
737
|
+
}
|
|
738
|
+
#membersOf(ids) {
|
|
739
|
+
return [...new Set(ids.flatMap((id) => [...this.#gestureMembers.get(id) ?? []]))];
|
|
740
|
+
}
|
|
741
|
+
#updateSimultaneous(winner) {
|
|
742
|
+
this.#simultaneousMembers = /* @__PURE__ */ new Set();
|
|
743
|
+
this.#simultaneousIds = /* @__PURE__ */ new Set();
|
|
744
|
+
for (const detector of winner.detectors.values()) for (const id of detector.simultaneous) {
|
|
745
|
+
if (winner.detectors.has(id)) {
|
|
746
|
+
this.#simultaneousIds.add(id);
|
|
747
|
+
continue;
|
|
748
|
+
}
|
|
749
|
+
for (const member of this.#gestureMembers.get(id) ?? []) this.#simultaneousMembers.add(member);
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
};
|
|
753
|
+
export { WebGestureArena };
|
|
754
|
+
|
|
755
|
+
//# sourceMappingURL=blotch-angular-lynx-arena-Cycr_O6y.mjs.map
|