@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.
@@ -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