cradova 3.15.0 → 3.15.2
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.js +110 -92
- package/dist/primitives/classes.d.ts +18 -3
- package/dist/primitives/types.d.ts +3 -4
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -605,82 +605,93 @@ class List {
|
|
|
605
605
|
state;
|
|
606
606
|
item;
|
|
607
607
|
length;
|
|
608
|
-
|
|
609
|
-
|
|
608
|
+
itemHeight = 35;
|
|
609
|
+
windowCoverage = 500;
|
|
610
|
+
overscan = 20;
|
|
611
|
+
scrollingDirection = "vertical";
|
|
612
|
+
opts;
|
|
613
|
+
columns = 1;
|
|
610
614
|
container;
|
|
611
|
-
firstItemIndex = 0;
|
|
612
|
-
lastItemIndex = 0;
|
|
613
615
|
rendered = false;
|
|
614
616
|
subscribers = [];
|
|
615
|
-
|
|
617
|
+
scrollPos = 0;
|
|
618
|
+
list;
|
|
619
|
+
startIndex = 0;
|
|
620
|
+
listContainer;
|
|
621
|
+
constructor(state, item, opts) {
|
|
616
622
|
this.state = state;
|
|
617
|
-
this.item = item || ((item2) => div(String(item2)));
|
|
623
|
+
this.item = item || ((item2, i2) => div(String(item2) + " " + i2));
|
|
618
624
|
this.length = state.length;
|
|
619
|
-
this.
|
|
620
|
-
this.
|
|
621
|
-
this.
|
|
622
|
-
this.
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
625
|
+
this.opts = opts;
|
|
626
|
+
this.itemHeight = opts?.itemHeight || 35;
|
|
627
|
+
this.columns = opts?.columns || 1;
|
|
628
|
+
this.windowCoverage = opts?.windowHeight || opts?.windowWidth || 500;
|
|
629
|
+
this.overscan = opts?.overscan || 20;
|
|
630
|
+
this.scrollingDirection = opts?.scrollingDirection || "vertical";
|
|
631
|
+
this.container = div({
|
|
632
|
+
className: this.opts?.className,
|
|
633
|
+
onscroll: (e) => {
|
|
634
|
+
this.scrollPos = Math.floor(this.scrollingDirection === "vertical" ? e.target.scrollTop : e.target.scrollLeft);
|
|
635
|
+
requestAnimationFrame(() => this.render());
|
|
636
|
+
},
|
|
637
|
+
style: {
|
|
638
|
+
overflowY: this.scrollingDirection === "vertical" ? "scroll" : "hidden",
|
|
639
|
+
overflowX: this.scrollingDirection === "horizontal" ? "scroll" : "hidden",
|
|
640
|
+
height: this.opts?.windowHeight ? `${this.opts?.windowHeight}px` : "500px",
|
|
641
|
+
width: this.opts?.windowWidth ? `${this.opts?.windowWidth}px` : "100%"
|
|
642
|
+
}
|
|
643
|
+
}, div({
|
|
644
|
+
id: "listContainer",
|
|
645
|
+
style: {
|
|
646
|
+
height: `${Math.round(this.length * this.itemHeight / this.columns)}px`
|
|
647
|
+
}
|
|
648
|
+
}, div({
|
|
649
|
+
id: "list",
|
|
650
|
+
className: this.opts?.className,
|
|
651
|
+
style: {
|
|
652
|
+
transform: this.scrollingDirection === "vertical" ? `translateY(${this.scrollPos}px)` : `translateX(${this.scrollPos}px)`
|
|
653
|
+
}
|
|
654
|
+
})));
|
|
655
|
+
this.listContainer = this.container.querySelector("#listContainer");
|
|
656
|
+
this.list = this.container.querySelector("#list");
|
|
629
657
|
}
|
|
630
658
|
get Element() {
|
|
631
|
-
if (this.rendered) {
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
const isBottom = entry.target === this.container.lastElementChild;
|
|
645
|
-
const isTop = !isBottom;
|
|
646
|
-
observer.unobserve(entry.target);
|
|
647
|
-
const index = Number(entry.target.getAttribute("data-index"));
|
|
648
|
-
if (isBottom) {
|
|
649
|
-
for (let i2 = index + 1;i2 < this.length; i2++) {
|
|
650
|
-
const item = this.item(this.state[i2]);
|
|
651
|
-
item.setAttribute("data-index", i2.toString());
|
|
652
|
-
this.container.appendChild(item);
|
|
653
|
-
}
|
|
654
|
-
for (let i2 = index - this.renderingRange;i2 > 0; i2--) {
|
|
655
|
-
this.container.removeChild(this.container.children[i2]);
|
|
656
|
-
}
|
|
657
|
-
this.firstItemIndex = Number(this.container.firstElementChild?.getAttribute("data-index") || 0);
|
|
658
|
-
this.lastItemIndex = Number(this.container.lastElementChild?.getAttribute("data-index") || 0);
|
|
659
|
-
}
|
|
660
|
-
if (isTop) {
|
|
661
|
-
for (let i2 = index - 1;i2 > 0; i2--) {
|
|
662
|
-
const item = this.item(this.state[i2]);
|
|
663
|
-
item.setAttribute("data-index", i2.toString());
|
|
664
|
-
this.container.appendChild(item);
|
|
665
|
-
}
|
|
666
|
-
for (let i2 = index + this.renderingRange;i2 < this.length; i2++) {
|
|
667
|
-
this.container.removeChild(this.container.children[i2]);
|
|
668
|
-
}
|
|
669
|
-
this.lastItemIndex = Number(this.container.lastElementChild?.getAttribute("data-index") || 0);
|
|
670
|
-
this.firstItemIndex = Number(this.container.firstElementChild?.getAttribute("data-index") || 0);
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
});
|
|
659
|
+
if (!this.rendered) {
|
|
660
|
+
this.render();
|
|
661
|
+
this.rendered = true;
|
|
662
|
+
const relativeScrolling = () => {
|
|
663
|
+
const rect = this.container.getBoundingClientRect();
|
|
664
|
+
if (rect.top < 0 && rect.bottom > window.innerHeight) {
|
|
665
|
+
this.scrollPos = Math.abs(rect.top);
|
|
666
|
+
requestAnimationFrame(() => this.render());
|
|
667
|
+
}
|
|
668
|
+
};
|
|
669
|
+
window.addEventListener("scroll", relativeScrolling);
|
|
670
|
+
window.CradovaEvent.after_page_is_killed.push(() => {
|
|
671
|
+
window.removeEventListener("scroll", relativeScrolling);
|
|
674
672
|
});
|
|
675
|
-
|
|
676
|
-
observer.observe(this.container.firstElementChild);
|
|
677
|
-
};
|
|
678
|
-
window.addEventListener("scroll", domObser);
|
|
679
|
-
window.CradovaEvent.after_page_is_killed.push(() => {
|
|
680
|
-
window.removeEventListener("scroll", domObser);
|
|
681
|
-
});
|
|
673
|
+
}
|
|
682
674
|
return this.container;
|
|
683
675
|
}
|
|
676
|
+
render() {
|
|
677
|
+
const startIndex = Math.floor(this.scrollPos / this.itemHeight) * this.columns;
|
|
678
|
+
this.list.style.transform = this.scrollingDirection === "vertical" ? `translateY(${Math.floor(this.scrollPos / this.itemHeight) * this.itemHeight}px)` : `translateX(${Math.floor(this.scrollPos / this.itemHeight) * this.itemHeight}px)`;
|
|
679
|
+
let renderedNodesCount = (Math.ceil(this.windowCoverage / this.itemHeight) + this.overscan) * this.columns;
|
|
680
|
+
renderedNodesCount = Math.min(this.length - startIndex, renderedNodesCount);
|
|
681
|
+
for (;this.list.firstElementChild; )
|
|
682
|
+
this.list.firstElementChild.remove();
|
|
683
|
+
let index = 0;
|
|
684
|
+
for (let i2 = 0;i2 < renderedNodesCount; i2++) {
|
|
685
|
+
index = i2 + startIndex;
|
|
686
|
+
if (this.state[index]) {
|
|
687
|
+
this.list.appendChild(this.item(this.state[index], index));
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
if (index + 1 === this.length) {
|
|
691
|
+
this.opts?.onScrollEnd?.();
|
|
692
|
+
}
|
|
693
|
+
this.startIndex = startIndex;
|
|
694
|
+
}
|
|
684
695
|
computed(listener) {
|
|
685
696
|
if (!listener) {
|
|
686
697
|
console.error(` ✘ Cradova err: listener ${String(listener)} is not a valid event name or function`);
|
|
@@ -704,34 +715,41 @@ class List {
|
|
|
704
715
|
}
|
|
705
716
|
diffDOMBeforeUpdatingState(newState) {
|
|
706
717
|
this.length = newState.length;
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
718
|
+
let startIndex = Math.floor(this.scrollPos / this.itemHeight) * this.columns;
|
|
719
|
+
startIndex = Math.floor(startIndex / this.columns) * this.columns;
|
|
720
|
+
let renderedNodesCount = this.list.childElementCount;
|
|
721
|
+
if (renderedNodesCount < this.overscan) {
|
|
722
|
+
this.state = newState;
|
|
723
|
+
this.render();
|
|
724
|
+
} else {
|
|
725
|
+
for (let i2 = 0;i2 < renderedNodesCount; i2++) {
|
|
726
|
+
const index = i2 + startIndex;
|
|
727
|
+
if (newState[index] === undefined) {
|
|
728
|
+
this.list.children[index]?.remove();
|
|
729
|
+
continue;
|
|
730
|
+
}
|
|
731
|
+
const item = this.item(newState[index], index);
|
|
732
|
+
if (this.list.children[index]) {
|
|
733
|
+
this.list.replaceChild(item, this.list.children[index]);
|
|
734
|
+
} else {
|
|
735
|
+
this.list.appendChild(item);
|
|
736
|
+
}
|
|
723
737
|
}
|
|
738
|
+
this.list.style.transform = this.scrollingDirection === "vertical" ? `translateY(${Math.floor(this.scrollPos / this.itemHeight) * this.itemHeight}px)` : `translateX(${Math.floor(this.scrollPos / this.itemHeight) * this.itemHeight}px)`;
|
|
739
|
+
this.state = newState;
|
|
724
740
|
}
|
|
725
|
-
this.
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
741
|
+
if (this.length !== newState.length) {
|
|
742
|
+
this.listContainer.style.height = `${Math.round(this.length * this.itemHeight / this.columns)}px`;
|
|
743
|
+
}
|
|
744
|
+
queueMicrotask(() => {
|
|
745
|
+
this.subscribers.forEach((sub) => {
|
|
746
|
+
const isComp = !isArrowFunc(sub);
|
|
747
|
+
if (isComp) {
|
|
748
|
+
compManager.recall(sub);
|
|
749
|
+
} else {
|
|
750
|
+
sub?.();
|
|
751
|
+
}
|
|
752
|
+
});
|
|
735
753
|
});
|
|
736
754
|
}
|
|
737
755
|
get data() {
|
|
@@ -52,14 +52,29 @@ export declare class Signal<Type extends Record<string, any> = any> {
|
|
|
52
52
|
*/
|
|
53
53
|
export declare class List<T> {
|
|
54
54
|
length: number;
|
|
55
|
+
private windowCoverage;
|
|
56
|
+
private overscan;
|
|
57
|
+
private scrollingDirection;
|
|
58
|
+
private opts?;
|
|
59
|
+
private columns;
|
|
55
60
|
private rendered;
|
|
56
61
|
subscribers: Function[];
|
|
57
|
-
|
|
58
|
-
|
|
62
|
+
scrollPos: number;
|
|
63
|
+
list: HTMLElement;
|
|
64
|
+
startIndex: number;
|
|
65
|
+
listContainer: HTMLElement;
|
|
66
|
+
constructor(state: T[], item?: (item: T, i: number) => HTMLElement, opts?: {
|
|
67
|
+
itemHeight?: number;
|
|
59
68
|
className?: string;
|
|
60
|
-
|
|
69
|
+
columns?: number;
|
|
70
|
+
windowHeight?: number;
|
|
71
|
+
windowWidth?: number;
|
|
72
|
+
overscan?: number;
|
|
73
|
+
scrollingDirection?: "vertical" | "horizontal";
|
|
74
|
+
onScrollEnd?: () => void;
|
|
61
75
|
});
|
|
62
76
|
get Element(): HTMLElement;
|
|
77
|
+
private render;
|
|
63
78
|
computed(listener?: (() => void) | Comp | ((ctx: Comp) => HTMLElement)): HTMLElement | undefined;
|
|
64
79
|
private diffDOMBeforeUpdatingState;
|
|
65
80
|
get data(): IterableIterator<T>;
|
|
@@ -2,11 +2,10 @@ import * as CSS from "csstype";
|
|
|
2
2
|
import { Page, RefInstance, Signal } from "./classes.js";
|
|
3
3
|
interface Attributes<E extends HTMLElement> {
|
|
4
4
|
ref?: [RefInstance<any>, string];
|
|
5
|
-
value?: any;
|
|
6
5
|
style?: Partial<CSS.Properties>;
|
|
7
|
-
[key: `data-${string}`]: string
|
|
8
|
-
[key: `aria-${string}`]: string
|
|
9
|
-
[key: `on${string}`]: (
|
|
6
|
+
[key: `data-${string}`]: string;
|
|
7
|
+
[key: `aria-${string}`]: string;
|
|
8
|
+
[key: `on${string}`]: (this: E, event: StandardEvents) => void;
|
|
10
9
|
}
|
|
11
10
|
type StandardEvents = KeyboardEvent | MouseEvent | TouchEvent | WheelEvent | DragEvent | ClipboardEvent | CompositionEvent | FocusEvent | InputEvent | AnimationEvent | TransitionEvent | Event;
|
|
12
11
|
type OmitFunctions<E> = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cradova",
|
|
3
|
-
"version": "3.15.
|
|
3
|
+
"version": "3.15.2",
|
|
4
4
|
"description": "Build Powerful ⚡ Web Apps with Ease",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -55,7 +55,8 @@
|
|
|
55
55
|
},
|
|
56
56
|
"homepage": "https://github.com/CodeDynasty-dev/cradova",
|
|
57
57
|
"dependencies": {
|
|
58
|
-
"csstype": "^3.1.3"
|
|
58
|
+
"csstype": "^3.1.3",
|
|
59
|
+
"virtualized-list": "^2.2.0"
|
|
59
60
|
},
|
|
60
61
|
"docmach": {
|
|
61
62
|
"docs-directory": "docs/docs",
|