bunnyquery 1.8.14 → 1.8.16
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/bunnyquery.js +251 -26
- package/dist/engine.cjs +189 -12
- package/dist/engine.cjs.map +1 -1
- package/dist/engine.d.mts +73 -0
- package/dist/engine.d.ts +73 -0
- package/dist/engine.mjs +189 -12
- package/dist/engine.mjs.map +1 -1
- package/package.json +1 -1
- package/src/engine/host.ts +14 -0
- package/src/engine/scroll_anchor.ts +366 -11
- package/src/engine/session.ts +11 -1
package/dist/engine.cjs
CHANGED
|
@@ -2580,6 +2580,9 @@ function shouldRescueInFlightMessage(m, ctx) {
|
|
|
2580
2580
|
// src/engine/scroll_anchor.ts
|
|
2581
2581
|
var ROW_KEY_ATTR = "data-row-key";
|
|
2582
2582
|
var ROW_POS_ATTR = "data-row-pos";
|
|
2583
|
+
var MAX_ALTS = 2;
|
|
2584
|
+
var ALT_SCAN_LIMIT = 64;
|
|
2585
|
+
var MAX_RETURN_SETTLES = 3;
|
|
2583
2586
|
var UNKNOWN_ROW_POS = "\0?";
|
|
2584
2587
|
function createScrollAnchor(options) {
|
|
2585
2588
|
var held = null;
|
|
@@ -2590,6 +2593,7 @@ function createScrollAnchor(options) {
|
|
|
2590
2593
|
var boxTop = box.getBoundingClientRect().top;
|
|
2591
2594
|
var kids = box.children;
|
|
2592
2595
|
var fallback = null;
|
|
2596
|
+
var fallbackAt = -1;
|
|
2593
2597
|
for (var i = 0; i < kids.length; i++) {
|
|
2594
2598
|
var el = kids[i];
|
|
2595
2599
|
if (!el || typeof el.getAttribute !== "function") continue;
|
|
@@ -2608,10 +2612,20 @@ function createScrollAnchor(options) {
|
|
|
2608
2612
|
scrollHeight: box.scrollHeight,
|
|
2609
2613
|
el
|
|
2610
2614
|
};
|
|
2611
|
-
if (rawPos === null)
|
|
2612
|
-
|
|
2615
|
+
if (rawPos === null) {
|
|
2616
|
+
cand.alts = collectAlts(box, boxTop, i + 1);
|
|
2617
|
+
return cand;
|
|
2618
|
+
}
|
|
2619
|
+
if (!fallback) {
|
|
2620
|
+
fallback = cand;
|
|
2621
|
+
fallbackAt = i;
|
|
2622
|
+
}
|
|
2623
|
+
}
|
|
2624
|
+
if (fallback) {
|
|
2625
|
+
fallback.alts = collectAlts(box, boxTop, fallbackAt + 1, true);
|
|
2626
|
+
return fallback;
|
|
2613
2627
|
}
|
|
2614
|
-
return
|
|
2628
|
+
return {
|
|
2615
2629
|
key: null,
|
|
2616
2630
|
top: 0,
|
|
2617
2631
|
pos: null,
|
|
@@ -2620,6 +2634,26 @@ function createScrollAnchor(options) {
|
|
|
2620
2634
|
el: null
|
|
2621
2635
|
};
|
|
2622
2636
|
}
|
|
2637
|
+
function collectAlts(box, boxTop, from, ordinaryOnly) {
|
|
2638
|
+
var out = [];
|
|
2639
|
+
var kids = box.children;
|
|
2640
|
+
var stop = Math.min(kids.length, from + ALT_SCAN_LIMIT);
|
|
2641
|
+
for (var i = from; i < stop && out.length < MAX_ALTS; i++) {
|
|
2642
|
+
var el = kids[i];
|
|
2643
|
+
if (!el || typeof el.getAttribute !== "function") continue;
|
|
2644
|
+
var key = el.getAttribute(ROW_KEY_ATTR);
|
|
2645
|
+
if (!key) continue;
|
|
2646
|
+
var rawPos = el.getAttribute(ROW_POS_ATTR);
|
|
2647
|
+
if (ordinaryOnly && rawPos !== null) continue;
|
|
2648
|
+
out.push({
|
|
2649
|
+
key,
|
|
2650
|
+
top: el.getBoundingClientRect().top - boxTop,
|
|
2651
|
+
pos: rawPos === null ? null : rawPos || UNKNOWN_ROW_POS,
|
|
2652
|
+
el
|
|
2653
|
+
});
|
|
2654
|
+
}
|
|
2655
|
+
return out.length ? out : void 0;
|
|
2656
|
+
}
|
|
2623
2657
|
function findRow(box, anchor) {
|
|
2624
2658
|
var el = anchor.el;
|
|
2625
2659
|
if (el && el.parentNode === box) return el;
|
|
@@ -2632,31 +2666,80 @@ function createScrollAnchor(options) {
|
|
|
2632
2666
|
}
|
|
2633
2667
|
return null;
|
|
2634
2668
|
}
|
|
2635
|
-
|
|
2669
|
+
var sawFrozen = false;
|
|
2670
|
+
var parked = null;
|
|
2671
|
+
var parkedStuck = false;
|
|
2672
|
+
var returning = false;
|
|
2673
|
+
var returnBudget = 0;
|
|
2674
|
+
var wroteTop = -1;
|
|
2675
|
+
var restoreExact = true;
|
|
2676
|
+
var restorePinned = false;
|
|
2677
|
+
function frozen() {
|
|
2678
|
+
var f = !!options.isFrozen && options.isFrozen();
|
|
2679
|
+
if (f) sawFrozen = true;
|
|
2680
|
+
return f;
|
|
2681
|
+
}
|
|
2682
|
+
function restore(anchor, unbounded) {
|
|
2683
|
+
if (frozen()) return;
|
|
2636
2684
|
var box = options.getBox();
|
|
2637
2685
|
if (!box || !anchor || options.isStuck()) return;
|
|
2638
2686
|
var el = findRow(box, anchor);
|
|
2639
2687
|
if (el) {
|
|
2640
2688
|
var livePos = el.getAttribute(ROW_POS_ATTR) || UNKNOWN_ROW_POS;
|
|
2641
|
-
if (anchor.pos !== null && anchor.pos !== UNKNOWN_ROW_POS && livePos !== UNKNOWN_ROW_POS && livePos !== anchor.pos)
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
}
|
|
2689
|
+
if (anchor.pos !== null && anchor.pos !== UNKNOWN_ROW_POS && livePos !== UNKNOWN_ROW_POS && livePos !== anchor.pos) el = null;
|
|
2690
|
+
}
|
|
2691
|
+
if (el) {
|
|
2645
2692
|
var boxTop = box.getBoundingClientRect().top;
|
|
2646
2693
|
var delta = el.getBoundingClientRect().top - boxTop - anchor.top;
|
|
2647
2694
|
var slack = Math.abs(box.scrollHeight - anchor.scrollHeight) + box.clientHeight;
|
|
2648
|
-
if (delta > slack || delta < -slack) {
|
|
2695
|
+
if (!unbounded && (delta > slack || delta < -slack)) {
|
|
2649
2696
|
lost(box, anchor);
|
|
2650
2697
|
return;
|
|
2651
2698
|
}
|
|
2699
|
+
var want = box.scrollTop + delta;
|
|
2652
2700
|
if (delta >= 1 || delta <= -1) box.scrollTop += delta;
|
|
2701
|
+
wroteTop = box.scrollTop;
|
|
2702
|
+
restorePinned = true;
|
|
2703
|
+
restoreExact = box.scrollTop >= want - 1 && box.scrollTop <= want + 1;
|
|
2653
2704
|
held = {
|
|
2654
2705
|
key: anchor.key,
|
|
2655
2706
|
top: anchor.top,
|
|
2656
2707
|
pos: anchor.pos,
|
|
2657
2708
|
scrollTop: box.scrollTop,
|
|
2658
2709
|
scrollHeight: box.scrollHeight,
|
|
2659
|
-
el
|
|
2710
|
+
el,
|
|
2711
|
+
// Carried, not dropped: one successful restore used to disarm the
|
|
2712
|
+
// standbys for every later hold.
|
|
2713
|
+
alts: anchor.alts
|
|
2714
|
+
};
|
|
2715
|
+
return;
|
|
2716
|
+
}
|
|
2717
|
+
var alts = anchor.alts;
|
|
2718
|
+
for (var ai = 0; alts && ai < alts.length; ai++) {
|
|
2719
|
+
var alt = alts[ai];
|
|
2720
|
+
var ael = findRow(box, { key: alt.key, top: alt.top, pos: alt.pos, scrollTop: anchor.scrollTop, scrollHeight: anchor.scrollHeight, el: alt.el });
|
|
2721
|
+
if (!ael) continue;
|
|
2722
|
+
if (alt.pos !== null && alt.pos !== UNKNOWN_ROW_POS) {
|
|
2723
|
+
var altLive = ael.getAttribute(ROW_POS_ATTR) || UNKNOWN_ROW_POS;
|
|
2724
|
+
if (altLive !== UNKNOWN_ROW_POS && altLive !== alt.pos) continue;
|
|
2725
|
+
}
|
|
2726
|
+
var aboxTop = box.getBoundingClientRect().top;
|
|
2727
|
+
var adelta = ael.getBoundingClientRect().top - aboxTop - alt.top;
|
|
2728
|
+
var aslack = Math.abs(box.scrollHeight - anchor.scrollHeight) + box.clientHeight;
|
|
2729
|
+
if (!unbounded && (adelta > aslack || adelta < -aslack)) continue;
|
|
2730
|
+
var awant = box.scrollTop + adelta;
|
|
2731
|
+
if (adelta >= 1 || adelta <= -1) box.scrollTop += adelta;
|
|
2732
|
+
wroteTop = box.scrollTop;
|
|
2733
|
+
restorePinned = true;
|
|
2734
|
+
restoreExact = box.scrollTop >= awant - 1 && box.scrollTop <= awant + 1;
|
|
2735
|
+
held = {
|
|
2736
|
+
key: alt.key,
|
|
2737
|
+
top: alt.top,
|
|
2738
|
+
pos: alt.pos,
|
|
2739
|
+
scrollTop: box.scrollTop,
|
|
2740
|
+
scrollHeight: box.scrollHeight,
|
|
2741
|
+
el: ael,
|
|
2742
|
+
alts: alts.slice(ai + 1)
|
|
2660
2743
|
};
|
|
2661
2744
|
return;
|
|
2662
2745
|
}
|
|
@@ -2667,9 +2750,13 @@ function createScrollAnchor(options) {
|
|
|
2667
2750
|
var grew = box.scrollHeight - anchor.scrollHeight;
|
|
2668
2751
|
if (grew > 0) {
|
|
2669
2752
|
box.scrollTop = anchor.scrollTop + grew;
|
|
2753
|
+
wroteTop = box.scrollTop;
|
|
2670
2754
|
return;
|
|
2671
2755
|
}
|
|
2672
|
-
if (options.rawFallback)
|
|
2756
|
+
if (options.rawFallback) {
|
|
2757
|
+
box.scrollTop = anchor.scrollTop;
|
|
2758
|
+
wroteTop = box.scrollTop;
|
|
2759
|
+
}
|
|
2673
2760
|
}
|
|
2674
2761
|
function preserve(mutate) {
|
|
2675
2762
|
var anchor = capture();
|
|
@@ -2678,9 +2765,17 @@ function createScrollAnchor(options) {
|
|
|
2678
2765
|
return result;
|
|
2679
2766
|
}
|
|
2680
2767
|
function remember() {
|
|
2768
|
+
var b0 = options.getBox();
|
|
2769
|
+
if (returning && b0 && b0.scrollTop !== wroteTop) release();
|
|
2770
|
+
if (frozen()) return;
|
|
2681
2771
|
held = capture();
|
|
2682
2772
|
}
|
|
2683
2773
|
function hold() {
|
|
2774
|
+
if (frozen()) return;
|
|
2775
|
+
if (sawFrozen) {
|
|
2776
|
+
settleReturn();
|
|
2777
|
+
return;
|
|
2778
|
+
}
|
|
2684
2779
|
var box = options.getBox();
|
|
2685
2780
|
if (!box || options.isStuck()) {
|
|
2686
2781
|
held = null;
|
|
@@ -2707,12 +2802,86 @@ function createScrollAnchor(options) {
|
|
|
2707
2802
|
if (prev === void 0) prev = 0;
|
|
2708
2803
|
var delta = h - prev;
|
|
2709
2804
|
if (delta === 0) return;
|
|
2805
|
+
if (frozen()) {
|
|
2806
|
+
foldFrozenGrowth(box, el, delta);
|
|
2807
|
+
return;
|
|
2808
|
+
}
|
|
2710
2809
|
if (el.getBoundingClientRect().top >= box.getBoundingClientRect().top) return;
|
|
2711
2810
|
box.scrollTop += delta;
|
|
2811
|
+
wroteTop = box.scrollTop;
|
|
2712
2812
|
if (held) held = capture();
|
|
2713
2813
|
}
|
|
2814
|
+
function park() {
|
|
2815
|
+
parked = capture();
|
|
2816
|
+
parkedStuck = !!options.isStuck();
|
|
2817
|
+
returning = true;
|
|
2818
|
+
returnBudget = MAX_RETURN_SETTLES;
|
|
2819
|
+
}
|
|
2820
|
+
function release() {
|
|
2821
|
+
parked = null;
|
|
2822
|
+
parkedStuck = false;
|
|
2823
|
+
returning = false;
|
|
2824
|
+
returnBudget = 0;
|
|
2825
|
+
}
|
|
2826
|
+
function pinBottom() {
|
|
2827
|
+
var box = options.getBox();
|
|
2828
|
+
if (!box) return;
|
|
2829
|
+
box.scrollTop = box.scrollHeight;
|
|
2830
|
+
wroteTop = box.scrollTop;
|
|
2831
|
+
}
|
|
2832
|
+
function settleReturn() {
|
|
2833
|
+
if (frozen()) return false;
|
|
2834
|
+
var wasFrozen = sawFrozen;
|
|
2835
|
+
sawFrozen = false;
|
|
2836
|
+
if (!returning && !wasFrozen) return false;
|
|
2837
|
+
if (returning) {
|
|
2838
|
+
if (returnBudget <= 0) {
|
|
2839
|
+
release();
|
|
2840
|
+
return false;
|
|
2841
|
+
}
|
|
2842
|
+
returnBudget--;
|
|
2843
|
+
}
|
|
2844
|
+
if (parkedStuck) {
|
|
2845
|
+
pinBottom();
|
|
2846
|
+
return true;
|
|
2847
|
+
}
|
|
2848
|
+
var target = parked || held;
|
|
2849
|
+
restoreExact = true;
|
|
2850
|
+
restorePinned = false;
|
|
2851
|
+
restore(target, true);
|
|
2852
|
+
parked = !restorePinned || !restoreExact ? target : null;
|
|
2853
|
+
returning = !!parked && returnBudget > 0;
|
|
2854
|
+
if (!returning) {
|
|
2855
|
+
parked = null;
|
|
2856
|
+
parkedStuck = false;
|
|
2857
|
+
returnBudget = 0;
|
|
2858
|
+
}
|
|
2859
|
+
return false;
|
|
2860
|
+
}
|
|
2861
|
+
function isReturning() {
|
|
2862
|
+
return returning;
|
|
2863
|
+
}
|
|
2864
|
+
function thaw() {
|
|
2865
|
+
settleReturn();
|
|
2866
|
+
}
|
|
2867
|
+
function foldFrozenGrowth(box, el, delta) {
|
|
2868
|
+
var elTop = el.getBoundingClientRect().top;
|
|
2869
|
+
foldInto(box, held, elTop, delta);
|
|
2870
|
+
foldInto(box, parked, elTop, delta);
|
|
2871
|
+
}
|
|
2872
|
+
function foldInto(box, a, elTop, delta) {
|
|
2873
|
+
if (!a || a.top >= 0) return;
|
|
2874
|
+
var rowEl = findRow(box, a);
|
|
2875
|
+
if (!rowEl) return;
|
|
2876
|
+
var within = elTop - rowEl.getBoundingClientRect().top;
|
|
2877
|
+
if (within < 0 || within >= rowEl.offsetHeight) return;
|
|
2878
|
+
if (within >= -a.top) return;
|
|
2879
|
+
a.top -= delta;
|
|
2880
|
+
a.scrollHeight += delta;
|
|
2881
|
+
}
|
|
2714
2882
|
function forget() {
|
|
2715
2883
|
held = null;
|
|
2884
|
+
release();
|
|
2716
2885
|
}
|
|
2717
2886
|
return {
|
|
2718
2887
|
capture,
|
|
@@ -2720,6 +2889,13 @@ function createScrollAnchor(options) {
|
|
|
2720
2889
|
preserve,
|
|
2721
2890
|
remember,
|
|
2722
2891
|
hold,
|
|
2892
|
+
park,
|
|
2893
|
+
settleReturn,
|
|
2894
|
+
isReturning,
|
|
2895
|
+
release,
|
|
2896
|
+
pinBottom,
|
|
2897
|
+
isFrozen: frozen,
|
|
2898
|
+
thaw,
|
|
2723
2899
|
absorb,
|
|
2724
2900
|
forget
|
|
2725
2901
|
};
|
|
@@ -5822,6 +5998,7 @@ var ChatSession = class {
|
|
|
5822
5998
|
releaseBgFlag();
|
|
5823
5999
|
self.updateHistoryCache();
|
|
5824
6000
|
self.host.notify();
|
|
6001
|
+
if (self.host.settleScroll) self.host.settleScroll();
|
|
5825
6002
|
}, function() {
|
|
5826
6003
|
releaseBgFlag();
|
|
5827
6004
|
self.host.notify();
|
|
@@ -5903,7 +6080,7 @@ var ChatSession = class {
|
|
|
5903
6080
|
self.drainBgTaskQueue();
|
|
5904
6081
|
}
|
|
5905
6082
|
if (!fetchMore) self.refreshLiveIndexState();
|
|
5906
|
-
if (!fetchMore) return self.host.scrollToBottomIfSticky();
|
|
6083
|
+
if (!fetchMore) return self.host.settleScroll ? self.host.settleScroll() : self.host.scrollToBottomIfSticky();
|
|
5907
6084
|
}).catch(function(err) {
|
|
5908
6085
|
console.warn("[chat-engine] getChatHistory failed", err);
|
|
5909
6086
|
}).then(function() {
|