@gridkitjs/dom 0.3.3 → 0.4.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.
- package/dist/index.d.ts +65 -23
- package/dist/index.js +240 -131
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -175,8 +175,7 @@ function attachChecklist(list, options) {
|
|
|
175
175
|
item.focus({ preventScroll: true });
|
|
176
176
|
}
|
|
177
177
|
}
|
|
178
|
-
|
|
179
|
-
setTabStop();
|
|
178
|
+
function focusPendingIfMounted() {
|
|
180
179
|
const item = pending === null ? null : itemAt(pending);
|
|
181
180
|
if (item === null) {
|
|
182
181
|
return;
|
|
@@ -186,6 +185,10 @@ function attachChecklist(list, options) {
|
|
|
186
185
|
if (focused === null || focused === document.body || list.contains(focused)) {
|
|
187
186
|
item.focus({ preventScroll: true });
|
|
188
187
|
}
|
|
188
|
+
}
|
|
189
|
+
const observer = new MutationObserver(() => {
|
|
190
|
+
setTabStop();
|
|
191
|
+
focusPendingIfMounted();
|
|
189
192
|
});
|
|
190
193
|
observer.observe(list, {
|
|
191
194
|
childList: true,
|
|
@@ -200,7 +203,11 @@ function attachChecklist(list, options) {
|
|
|
200
203
|
setCount(next) {
|
|
201
204
|
count = next;
|
|
202
205
|
active = Math.max(0, Math.min(active, count - 1));
|
|
206
|
+
if (pending !== null) {
|
|
207
|
+
pending = count === 0 ? null : Math.min(pending, count - 1);
|
|
208
|
+
}
|
|
203
209
|
setTabStop();
|
|
210
|
+
focusPendingIfMounted();
|
|
204
211
|
},
|
|
205
212
|
focusItem: moveTo,
|
|
206
213
|
detach() {
|
|
@@ -322,61 +329,77 @@ function attachContextMenuTrigger(root, options) {
|
|
|
322
329
|
import { applyColumnResize } from "@gridkitjs/core";
|
|
323
330
|
|
|
324
331
|
// src/pointerGesture.ts
|
|
325
|
-
function
|
|
326
|
-
return press.button === 0 && press.isPrimary;
|
|
332
|
+
function mayStartGesture(press, signal) {
|
|
333
|
+
return press.button === 0 && press.isPrimary && signal?.aborted !== true;
|
|
327
334
|
}
|
|
328
|
-
function startPointerGesture(element, pointerId, handlers) {
|
|
335
|
+
function startPointerGesture(element, pointerId, handlers, signal) {
|
|
329
336
|
element.setPointerCapture(pointerId);
|
|
330
337
|
function stop() {
|
|
331
338
|
element.removeEventListener("pointermove", move);
|
|
332
339
|
element.removeEventListener("pointerup", end);
|
|
333
340
|
element.removeEventListener("pointercancel", cancel);
|
|
334
341
|
window.removeEventListener("keydown", onKeyDown2);
|
|
342
|
+
signal?.removeEventListener("abort", abandon);
|
|
335
343
|
if (element.hasPointerCapture(pointerId)) {
|
|
336
344
|
element.releasePointerCapture(pointerId);
|
|
337
345
|
}
|
|
338
346
|
}
|
|
339
347
|
function move(event) {
|
|
340
|
-
|
|
348
|
+
if (event.pointerId === pointerId) {
|
|
349
|
+
handlers.onMove(event);
|
|
350
|
+
}
|
|
341
351
|
}
|
|
342
|
-
function end() {
|
|
343
|
-
|
|
344
|
-
|
|
352
|
+
function end(event) {
|
|
353
|
+
if (event.pointerId === pointerId) {
|
|
354
|
+
stop();
|
|
355
|
+
handlers.onEnd();
|
|
356
|
+
}
|
|
345
357
|
}
|
|
346
|
-
function cancel() {
|
|
358
|
+
function cancel(event) {
|
|
359
|
+
if (event.pointerId === pointerId) {
|
|
360
|
+
abandon();
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
function abandon() {
|
|
347
364
|
stop();
|
|
348
365
|
handlers.onCancel();
|
|
349
366
|
}
|
|
350
367
|
function onKeyDown2(event) {
|
|
351
368
|
if (event.key === "Escape") {
|
|
352
|
-
|
|
369
|
+
abandon();
|
|
353
370
|
}
|
|
354
371
|
}
|
|
355
372
|
element.addEventListener("pointermove", move);
|
|
356
373
|
element.addEventListener("pointerup", end);
|
|
357
374
|
element.addEventListener("pointercancel", cancel);
|
|
358
375
|
window.addEventListener("keydown", onKeyDown2);
|
|
376
|
+
signal?.addEventListener("abort", abandon);
|
|
359
377
|
}
|
|
360
378
|
|
|
361
379
|
// src/columnResize.ts
|
|
362
380
|
function startColumnResizeGesture(handle, press, session, handlers) {
|
|
363
|
-
if (!
|
|
381
|
+
if (!mayStartGesture(press, handlers.signal)) {
|
|
364
382
|
return false;
|
|
365
383
|
}
|
|
366
384
|
press.preventDefault();
|
|
367
385
|
let width = session.startWidth;
|
|
368
|
-
startPointerGesture(
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
386
|
+
startPointerGesture(
|
|
387
|
+
handle,
|
|
388
|
+
press.pointerId,
|
|
389
|
+
{
|
|
390
|
+
onMove(event) {
|
|
391
|
+
width = applyColumnResize(session, event.clientX);
|
|
392
|
+
handlers.onMove(width);
|
|
393
|
+
},
|
|
394
|
+
onEnd() {
|
|
395
|
+
handlers.onEnd(width === session.startWidth ? null : width);
|
|
396
|
+
},
|
|
397
|
+
onCancel() {
|
|
398
|
+
handlers.onCancel();
|
|
399
|
+
}
|
|
375
400
|
},
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
}
|
|
379
|
-
});
|
|
401
|
+
handlers.signal
|
|
402
|
+
);
|
|
380
403
|
return true;
|
|
381
404
|
}
|
|
382
405
|
function measureColumnContent(table, columnId) {
|
|
@@ -503,41 +526,43 @@ var NO_DRAG = {
|
|
|
503
526
|
ghostTransform: null
|
|
504
527
|
};
|
|
505
528
|
function startDragReorder(id, grabElement, press, handlers) {
|
|
506
|
-
if (!
|
|
529
|
+
if (!mayStartGesture(press, handlers.signal)) {
|
|
507
530
|
return false;
|
|
508
531
|
}
|
|
509
|
-
const { pointerId, clientX: startX } = press;
|
|
532
|
+
const { pointerId, clientX: startX, clientY: startY } = press;
|
|
510
533
|
const grabX = startX - grabElement.getBoundingClientRect().left;
|
|
511
|
-
let
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
534
|
+
let phase = { kind: "pressed" };
|
|
535
|
+
startPointerGesture(
|
|
536
|
+
grabElement,
|
|
537
|
+
pointerId,
|
|
538
|
+
{
|
|
539
|
+
onMove(moveEvent) {
|
|
540
|
+
const { clientX, clientY } = moveEvent;
|
|
541
|
+
if (phase.kind === "pressed" && Math.hypot(clientX - startX, clientY - startY) < DRAG_THRESHOLD) {
|
|
518
542
|
return;
|
|
519
543
|
}
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
544
|
+
phase = {
|
|
545
|
+
kind: "dragging",
|
|
546
|
+
target: handlers.resolveTarget(clientX, clientY, id)
|
|
547
|
+
};
|
|
548
|
+
handlers.onState({
|
|
549
|
+
draggedId: id,
|
|
550
|
+
dropTarget: phase.target,
|
|
551
|
+
ghostTransform: `translate(${String(clientX - grabX)}px, ${String(clientY)}px)`
|
|
552
|
+
});
|
|
553
|
+
},
|
|
554
|
+
onEnd() {
|
|
555
|
+
handlers.onState(NO_DRAG);
|
|
556
|
+
if (phase.kind === "dragging" && phase.target !== null) {
|
|
557
|
+
handlers.onDrop(phase.target, id);
|
|
558
|
+
}
|
|
559
|
+
},
|
|
560
|
+
onCancel() {
|
|
561
|
+
handlers.onState(NO_DRAG);
|
|
534
562
|
}
|
|
535
563
|
},
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
handlers.onState(NO_DRAG);
|
|
539
|
-
}
|
|
540
|
-
});
|
|
564
|
+
handlers.signal
|
|
565
|
+
);
|
|
541
566
|
return true;
|
|
542
567
|
}
|
|
543
568
|
|
|
@@ -640,6 +665,25 @@ function createGridFocus(initialOptions) {
|
|
|
640
665
|
}
|
|
641
666
|
return snapshot.focus;
|
|
642
667
|
}
|
|
668
|
+
function dropPendingMove() {
|
|
669
|
+
pendingMove = null;
|
|
670
|
+
}
|
|
671
|
+
function listenForTakeover(root) {
|
|
672
|
+
function onFocusOut(event) {
|
|
673
|
+
const to = event.relatedTarget;
|
|
674
|
+
if (to instanceof Node && !root.contains(to)) {
|
|
675
|
+
dropPendingMove();
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
root.addEventListener("focusout", onFocusOut);
|
|
679
|
+
root.addEventListener("wheel", dropPendingMove, { passive: true });
|
|
680
|
+
root.addEventListener("pointerdown", dropPendingMove);
|
|
681
|
+
return () => {
|
|
682
|
+
root.removeEventListener("focusout", onFocusOut);
|
|
683
|
+
root.removeEventListener("wheel", dropPendingMove);
|
|
684
|
+
root.removeEventListener("pointerdown", dropPendingMove);
|
|
685
|
+
};
|
|
686
|
+
}
|
|
643
687
|
function focusCell(rowIndex, columnIndex) {
|
|
644
688
|
const next = clampFocus(
|
|
645
689
|
{ rowIndex, columnIndex },
|
|
@@ -684,9 +728,11 @@ function createGridFocus(initialOptions) {
|
|
|
684
728
|
focusCell(next.rowIndex, next.columnIndex);
|
|
685
729
|
return true;
|
|
686
730
|
},
|
|
687
|
-
attach(next) {
|
|
731
|
+
attach(next, root) {
|
|
688
732
|
rows = next;
|
|
733
|
+
const stopListening = root == null ? void 0 : listenForTakeover(root);
|
|
689
734
|
return () => {
|
|
735
|
+
stopListening?.();
|
|
690
736
|
if (rows === next) {
|
|
691
737
|
rows = null;
|
|
692
738
|
}
|
|
@@ -716,20 +762,36 @@ function createGridFocus(initialOptions) {
|
|
|
716
762
|
}
|
|
717
763
|
|
|
718
764
|
// src/infiniteScroll.ts
|
|
765
|
+
var IDLE = { kind: "idle" };
|
|
766
|
+
var REQUESTED = { kind: "requested" };
|
|
767
|
+
var LOADING = { kind: "loading" };
|
|
768
|
+
var DETACHED = { kind: "detached" };
|
|
769
|
+
function afterUpdate(state, loading, hasMoreChanged) {
|
|
770
|
+
if (loading) {
|
|
771
|
+
return LOADING;
|
|
772
|
+
}
|
|
773
|
+
return state.kind === "loading" || hasMoreChanged ? IDLE : state;
|
|
774
|
+
}
|
|
719
775
|
function attachInfiniteScroll(root, options) {
|
|
720
776
|
let latest = options;
|
|
721
777
|
let intersecting = false;
|
|
722
|
-
let
|
|
723
|
-
let wasLoading = options.isLoadingMore ?? false;
|
|
778
|
+
let state = options.isLoadingMore ?? false ? LOADING : IDLE;
|
|
724
779
|
let observer = null;
|
|
725
780
|
let observed = null;
|
|
726
781
|
function maybeLoadMore() {
|
|
727
|
-
if (!intersecting || !latest.hasMore
|
|
782
|
+
if (state.kind !== "idle" || !intersecting || !latest.hasMore) {
|
|
728
783
|
return;
|
|
729
784
|
}
|
|
730
|
-
|
|
785
|
+
state = REQUESTED;
|
|
731
786
|
latest.onLoadMore?.();
|
|
732
787
|
}
|
|
788
|
+
function report(isIntersecting) {
|
|
789
|
+
intersecting = isIntersecting;
|
|
790
|
+
if (!intersecting && state.kind === "requested") {
|
|
791
|
+
state = IDLE;
|
|
792
|
+
}
|
|
793
|
+
maybeLoadMore();
|
|
794
|
+
}
|
|
733
795
|
function disconnect() {
|
|
734
796
|
observer?.disconnect();
|
|
735
797
|
observer = null;
|
|
@@ -749,11 +811,9 @@ function attachInfiniteScroll(root, options) {
|
|
|
749
811
|
observer = new IntersectionObserver(
|
|
750
812
|
(entries) => {
|
|
751
813
|
const entry = entries[entries.length - 1];
|
|
752
|
-
if (entry
|
|
753
|
-
|
|
814
|
+
if (entry !== void 0) {
|
|
815
|
+
report(entry.isIntersecting);
|
|
754
816
|
}
|
|
755
|
-
intersecting = entry.isIntersecting;
|
|
756
|
-
maybeLoadMore();
|
|
757
817
|
},
|
|
758
818
|
{ root, rootMargin }
|
|
759
819
|
);
|
|
@@ -763,16 +823,19 @@ function attachInfiniteScroll(root, options) {
|
|
|
763
823
|
observe();
|
|
764
824
|
return {
|
|
765
825
|
update(next) {
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
if (wasLoading && !loading) {
|
|
769
|
-
fired = false;
|
|
770
|
-
maybeLoadMore();
|
|
826
|
+
if (state.kind === "detached") {
|
|
827
|
+
return;
|
|
771
828
|
}
|
|
772
|
-
|
|
829
|
+
const hasMoreChanged = next.hasMore !== latest.hasMore;
|
|
830
|
+
latest = next;
|
|
831
|
+
state = afterUpdate(state, next.isLoadingMore ?? false, hasMoreChanged);
|
|
773
832
|
observe();
|
|
833
|
+
maybeLoadMore();
|
|
774
834
|
},
|
|
775
|
-
detach
|
|
835
|
+
detach() {
|
|
836
|
+
disconnect();
|
|
837
|
+
state = DETACHED;
|
|
838
|
+
}
|
|
776
839
|
};
|
|
777
840
|
}
|
|
778
841
|
|
|
@@ -792,6 +855,8 @@ var MOVES = {
|
|
|
792
855
|
Home: "first",
|
|
793
856
|
End: "last"
|
|
794
857
|
};
|
|
858
|
+
var IDLE2 = { kind: "idle" };
|
|
859
|
+
var AWAY = { kind: "away" };
|
|
795
860
|
function idOf(item) {
|
|
796
861
|
return item.getAttribute("data-gridkit-menu-item") ?? "";
|
|
797
862
|
}
|
|
@@ -809,10 +874,8 @@ function isTypeahead(event) {
|
|
|
809
874
|
return /^\S$/u.test(event.key) && !event.ctrlKey && !event.metaKey && !event.altKey;
|
|
810
875
|
}
|
|
811
876
|
function attachMenu(panel, options) {
|
|
812
|
-
let
|
|
813
|
-
let
|
|
814
|
-
let hovered = null;
|
|
815
|
-
let hoverTimer;
|
|
877
|
+
let typeahead = IDLE2;
|
|
878
|
+
let hover = AWAY;
|
|
816
879
|
function items() {
|
|
817
880
|
return Array.from(panel.querySelectorAll(ITEM2));
|
|
818
881
|
}
|
|
@@ -841,21 +904,58 @@ function attachMenu(panel, options) {
|
|
|
841
904
|
options.onActivate(idOf(item));
|
|
842
905
|
}
|
|
843
906
|
}
|
|
844
|
-
function
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
907
|
+
function endTyping() {
|
|
908
|
+
if (typeahead.kind === "typing") {
|
|
909
|
+
window.clearTimeout(typeahead.timer);
|
|
910
|
+
}
|
|
911
|
+
typeahead = IDLE2;
|
|
912
|
+
}
|
|
913
|
+
function endHover() {
|
|
914
|
+
if (hover.kind === "resting") {
|
|
915
|
+
window.clearTimeout(hover.timer);
|
|
916
|
+
}
|
|
917
|
+
hover = AWAY;
|
|
918
|
+
}
|
|
919
|
+
function type(key, all, from) {
|
|
920
|
+
const typed = (typeahead.kind === "typing" ? typeahead.typed : "") + key;
|
|
921
|
+
endTyping();
|
|
922
|
+
typeahead = {
|
|
923
|
+
kind: "typing",
|
|
924
|
+
typed,
|
|
925
|
+
timer: window.setTimeout(() => {
|
|
926
|
+
typeahead = IDLE2;
|
|
927
|
+
}, TYPEAHEAD_TIMEOUT)
|
|
928
|
+
};
|
|
850
929
|
const match = all[typeaheadIndex(all.map(labelOf), from, typed)];
|
|
851
930
|
if (match !== void 0) {
|
|
852
931
|
focus(match);
|
|
853
932
|
}
|
|
854
933
|
}
|
|
934
|
+
function rest(item) {
|
|
935
|
+
hover = {
|
|
936
|
+
kind: "resting",
|
|
937
|
+
item,
|
|
938
|
+
timer: window.setTimeout(() => {
|
|
939
|
+
hover = { kind: "rested", item };
|
|
940
|
+
if (opensSubmenu(item) && !isDisabled(item)) {
|
|
941
|
+
openSubmenu(item, "none");
|
|
942
|
+
} else {
|
|
943
|
+
options.onCollapseSubmenu?.();
|
|
944
|
+
}
|
|
945
|
+
}, HOVER_DELAY)
|
|
946
|
+
};
|
|
947
|
+
}
|
|
855
948
|
function onKeyDown2(event) {
|
|
856
|
-
if (event.isComposing) {
|
|
949
|
+
if (event.isComposing || !actOnKey(event)) {
|
|
857
950
|
return;
|
|
858
951
|
}
|
|
952
|
+
event.preventDefault();
|
|
953
|
+
endHover();
|
|
954
|
+
if (!isTypeahead(event)) {
|
|
955
|
+
endTyping();
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
function actOnKey(event) {
|
|
859
959
|
const all = items();
|
|
860
960
|
const item = itemOf(event.target);
|
|
861
961
|
const from = item === null ? -1 : all.indexOf(item);
|
|
@@ -882,11 +982,11 @@ function attachMenu(panel, options) {
|
|
|
882
982
|
} else if (event.key === "Tab") {
|
|
883
983
|
options.onClose("tab");
|
|
884
984
|
} else if (isTypeahead(event)) {
|
|
885
|
-
|
|
985
|
+
type(event.key, all, from);
|
|
886
986
|
} else {
|
|
887
|
-
return;
|
|
987
|
+
return false;
|
|
888
988
|
}
|
|
889
|
-
|
|
989
|
+
return true;
|
|
890
990
|
}
|
|
891
991
|
function onFocusIn(event) {
|
|
892
992
|
const item = itemOf(event.target);
|
|
@@ -908,24 +1008,16 @@ function attachMenu(panel, options) {
|
|
|
908
1008
|
if (item !== null && document.activeElement !== item) {
|
|
909
1009
|
focus(item);
|
|
910
1010
|
}
|
|
911
|
-
if (item ===
|
|
1011
|
+
if (hover.kind !== "away" && hover.item === item) {
|
|
912
1012
|
return;
|
|
913
1013
|
}
|
|
914
|
-
|
|
915
|
-
window.clearTimeout(hoverTimer);
|
|
1014
|
+
endHover();
|
|
916
1015
|
if (item !== null) {
|
|
917
|
-
|
|
918
|
-
if (opensSubmenu(item) && !isDisabled(item)) {
|
|
919
|
-
openSubmenu(item, "none");
|
|
920
|
-
} else {
|
|
921
|
-
options.onCollapseSubmenu?.();
|
|
922
|
-
}
|
|
923
|
-
}, HOVER_DELAY);
|
|
1016
|
+
rest(item);
|
|
924
1017
|
}
|
|
925
1018
|
}
|
|
926
1019
|
function onPointerLeave() {
|
|
927
|
-
|
|
928
|
-
window.clearTimeout(hoverTimer);
|
|
1020
|
+
endHover();
|
|
929
1021
|
}
|
|
930
1022
|
const focused = itemOf(document.activeElement);
|
|
931
1023
|
setTabStop(focused ?? items()[0]);
|
|
@@ -943,8 +1035,8 @@ function attachMenu(panel, options) {
|
|
|
943
1035
|
}
|
|
944
1036
|
},
|
|
945
1037
|
detach() {
|
|
946
|
-
|
|
947
|
-
|
|
1038
|
+
endTyping();
|
|
1039
|
+
endHover();
|
|
948
1040
|
panel.removeEventListener("keydown", onKeyDown2);
|
|
949
1041
|
panel.removeEventListener("focusin", onFocusIn);
|
|
950
1042
|
panel.removeEventListener("click", onClick);
|
|
@@ -1238,15 +1330,18 @@ function attachOverlay(anchor, panel, options) {
|
|
|
1238
1330
|
if (settlingFrame !== null) {
|
|
1239
1331
|
cancelAnimationFrame(settlingFrame);
|
|
1240
1332
|
}
|
|
1241
|
-
if (
|
|
1242
|
-
|
|
1333
|
+
if (!focusInside) {
|
|
1334
|
+
return;
|
|
1243
1335
|
}
|
|
1336
|
+
const target = returnFocusTo?.isConnected === true ? returnFocusTo : options.returnFocusFallback?.();
|
|
1337
|
+
target?.focus({ preventScroll: true });
|
|
1244
1338
|
}
|
|
1245
1339
|
return detach;
|
|
1246
1340
|
}
|
|
1247
1341
|
|
|
1248
1342
|
// src/rowVirtualizer.ts
|
|
1249
1343
|
import { visibleRange } from "@gridkitjs/core";
|
|
1344
|
+
var READY = { kind: "ready" };
|
|
1250
1345
|
function sameRange(a, b) {
|
|
1251
1346
|
return a.startIndex === b.startIndex && a.endIndex === b.endIndex && a.offsetBefore === b.offsetBefore && a.offsetAfter === b.offsetAfter;
|
|
1252
1347
|
}
|
|
@@ -1256,13 +1351,12 @@ function createRowVirtualizer(scrollElement, options) {
|
|
|
1256
1351
|
let scrollTop = scrollElement.scrollTop;
|
|
1257
1352
|
let viewportHeight = scrollElement.clientHeight;
|
|
1258
1353
|
let range = null;
|
|
1259
|
-
let
|
|
1260
|
-
let pendingScroll;
|
|
1354
|
+
let phase = READY;
|
|
1261
1355
|
const elements = /* @__PURE__ */ new Map();
|
|
1262
1356
|
const indexByElement = /* @__PURE__ */ new Map();
|
|
1263
1357
|
const refCallbacks = /* @__PURE__ */ new Map();
|
|
1264
1358
|
function recompute() {
|
|
1265
|
-
if (destroyed) {
|
|
1359
|
+
if (phase.kind === "destroyed") {
|
|
1266
1360
|
return;
|
|
1267
1361
|
}
|
|
1268
1362
|
const next = visibleRange(
|
|
@@ -1313,6 +1407,9 @@ function createRowVirtualizer(scrollElement, options) {
|
|
|
1313
1407
|
recompute();
|
|
1314
1408
|
return {
|
|
1315
1409
|
setRowCount(count) {
|
|
1410
|
+
if (phase.kind === "awaiting-row" && phase.index >= count) {
|
|
1411
|
+
phase = READY;
|
|
1412
|
+
}
|
|
1316
1413
|
heights = Array.from({ length: count }, (_, index) => heights[index]);
|
|
1317
1414
|
recompute();
|
|
1318
1415
|
},
|
|
@@ -1330,15 +1427,15 @@ function createRowVirtualizer(scrollElement, options) {
|
|
|
1330
1427
|
indexByElement.delete(previous);
|
|
1331
1428
|
elements.delete(index);
|
|
1332
1429
|
}
|
|
1333
|
-
if (element === null || destroyed) {
|
|
1430
|
+
if (element === null || phase.kind === "destroyed") {
|
|
1334
1431
|
return;
|
|
1335
1432
|
}
|
|
1336
1433
|
elements.set(index, element);
|
|
1337
1434
|
indexByElement.set(element, index);
|
|
1338
1435
|
rowObserver.observe(element);
|
|
1339
|
-
if (
|
|
1340
|
-
element.scrollIntoView(
|
|
1341
|
-
|
|
1436
|
+
if (phase.kind === "awaiting-row" && phase.index === index) {
|
|
1437
|
+
element.scrollIntoView(phase.options);
|
|
1438
|
+
phase = READY;
|
|
1342
1439
|
}
|
|
1343
1440
|
};
|
|
1344
1441
|
refCallbacks.set(index, callback);
|
|
@@ -1346,21 +1443,21 @@ function createRowVirtualizer(scrollElement, options) {
|
|
|
1346
1443
|
return callback;
|
|
1347
1444
|
},
|
|
1348
1445
|
scrollToIndex(index, scrollOptions) {
|
|
1349
|
-
if (heights.length === 0) {
|
|
1446
|
+
if (phase.kind === "destroyed" || heights.length === 0) {
|
|
1350
1447
|
return;
|
|
1351
1448
|
}
|
|
1352
1449
|
const clamped = Math.max(0, Math.min(index, heights.length - 1));
|
|
1353
1450
|
const mounted = elements.get(clamped);
|
|
1354
1451
|
if (mounted !== void 0) {
|
|
1452
|
+
phase = READY;
|
|
1355
1453
|
mounted.scrollIntoView(scrollOptions);
|
|
1356
1454
|
return;
|
|
1357
1455
|
}
|
|
1358
|
-
|
|
1456
|
+
phase = { kind: "awaiting-row", index: clamped, options: scrollOptions };
|
|
1359
1457
|
scrollElement.scrollTop = estimateOffsetBefore(clamped);
|
|
1360
1458
|
},
|
|
1361
1459
|
destroy() {
|
|
1362
|
-
|
|
1363
|
-
pendingScroll = void 0;
|
|
1460
|
+
phase = { kind: "destroyed" };
|
|
1364
1461
|
scrollElement.removeEventListener("scroll", handleScroll);
|
|
1365
1462
|
viewportObserver.disconnect();
|
|
1366
1463
|
rowObserver.disconnect();
|
|
@@ -1589,17 +1686,26 @@ function createFrame(bodyHtml) {
|
|
|
1589
1686
|
}
|
|
1590
1687
|
function load(frame) {
|
|
1591
1688
|
return new Promise((resolve, reject) => {
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1689
|
+
const removal = new MutationObserver(() => {
|
|
1690
|
+
if (!frame.isConnected) {
|
|
1691
|
+
settle();
|
|
1692
|
+
reject(new Error("The print frame was removed before it loaded."));
|
|
1693
|
+
}
|
|
1694
|
+
});
|
|
1695
|
+
function loaded() {
|
|
1696
|
+
settle();
|
|
1697
|
+
if (frame.contentWindow === null) {
|
|
1698
|
+
reject(new Error("The print frame has no window."));
|
|
1699
|
+
} else {
|
|
1700
|
+
resolve(frame.contentWindow);
|
|
1701
|
+
}
|
|
1702
|
+
}
|
|
1703
|
+
function settle() {
|
|
1704
|
+
removal.disconnect();
|
|
1705
|
+
frame.removeEventListener("load", loaded);
|
|
1706
|
+
}
|
|
1707
|
+
frame.addEventListener("load", loaded);
|
|
1708
|
+
removal.observe(document.body, { childList: true });
|
|
1603
1709
|
document.body.append(frame);
|
|
1604
1710
|
});
|
|
1605
1711
|
}
|
|
@@ -1610,7 +1716,7 @@ function fill(view, { title, styles }) {
|
|
|
1610
1716
|
style.textContent = styles;
|
|
1611
1717
|
frameDocument.head.append(style);
|
|
1612
1718
|
}
|
|
1613
|
-
function print(view) {
|
|
1719
|
+
async function print(view) {
|
|
1614
1720
|
const listeners = [
|
|
1615
1721
|
[view, "afterprint"],
|
|
1616
1722
|
...RETURN_EVENTS.flatMap((type) => [
|
|
@@ -1618,19 +1724,22 @@ function print(view) {
|
|
|
1618
1724
|
[window, type]
|
|
1619
1725
|
])
|
|
1620
1726
|
];
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
target.addEventListener(type, done, { capture: true });
|
|
1630
|
-
}
|
|
1727
|
+
let done = () => void 0;
|
|
1728
|
+
const closed = new Promise((resolve) => {
|
|
1729
|
+
done = resolve;
|
|
1730
|
+
});
|
|
1731
|
+
for (const [target, type] of listeners) {
|
|
1732
|
+
target.addEventListener(type, done, { capture: true });
|
|
1733
|
+
}
|
|
1734
|
+
try {
|
|
1631
1735
|
view.focus();
|
|
1632
1736
|
view.print();
|
|
1633
|
-
|
|
1737
|
+
await closed;
|
|
1738
|
+
} finally {
|
|
1739
|
+
for (const [target, type] of listeners) {
|
|
1740
|
+
target.removeEventListener(type, done, { capture: true });
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1634
1743
|
}
|
|
1635
1744
|
async function printDocument(options) {
|
|
1636
1745
|
if (printing) {
|