@ship-ui/core 0.19.5 → 0.22.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/README.md +3 -0
- package/assets/mcp/components.json +66 -4243
- package/bin/mcp/index.js +6027 -273
- package/bin/ship-fg-scanner +0 -0
- package/bin/ship-fg.mjs +14 -12
- package/bin/src/subset.ts +3 -1
- package/fesm2022/ship-ui-core-sh-form-field-experimental.mjs +42 -0
- package/fesm2022/ship-ui-core-sh-form-field-experimental.mjs.map +1 -0
- package/fesm2022/ship-ui-core-ship-accordion.mjs +127 -0
- package/fesm2022/ship-ui-core-ship-accordion.mjs.map +1 -0
- package/fesm2022/ship-ui-core-ship-alert.mjs +305 -0
- package/fesm2022/ship-ui-core-ship-alert.mjs.map +1 -0
- package/fesm2022/ship-ui-core-ship-blueprint.mjs +1156 -0
- package/fesm2022/ship-ui-core-ship-blueprint.mjs.map +1 -0
- package/fesm2022/ship-ui-core-ship-button-group.mjs +41 -0
- package/fesm2022/ship-ui-core-ship-button-group.mjs.map +1 -0
- package/fesm2022/ship-ui-core-ship-button.mjs +38 -0
- package/fesm2022/ship-ui-core-ship-button.mjs.map +1 -0
- package/fesm2022/ship-ui-core-ship-card.mjs +35 -0
- package/fesm2022/ship-ui-core-ship-card.mjs.map +1 -0
- package/fesm2022/ship-ui-core-ship-checkbox.mjs +113 -0
- package/fesm2022/ship-ui-core-ship-checkbox.mjs.map +1 -0
- package/fesm2022/ship-ui-core-ship-chip.mjs +44 -0
- package/fesm2022/ship-ui-core-ship-chip.mjs.map +1 -0
- package/fesm2022/ship-ui-core-ship-color-picker.mjs +947 -0
- package/fesm2022/ship-ui-core-ship-color-picker.mjs.map +1 -0
- package/fesm2022/ship-ui-core-ship-datepicker.mjs +951 -0
- package/fesm2022/ship-ui-core-ship-datepicker.mjs.map +1 -0
- package/fesm2022/ship-ui-core-ship-dialog.mjs +263 -0
- package/fesm2022/ship-ui-core-ship-dialog.mjs.map +1 -0
- package/fesm2022/ship-ui-core-ship-divider.mjs +22 -0
- package/fesm2022/ship-ui-core-ship-divider.mjs.map +1 -0
- package/fesm2022/ship-ui-core-ship-event-card.mjs +50 -0
- package/fesm2022/ship-ui-core-ship-event-card.mjs.map +1 -0
- package/fesm2022/ship-ui-core-ship-file-upload.mjs +112 -0
- package/fesm2022/ship-ui-core-ship-file-upload.mjs.map +1 -0
- package/fesm2022/ship-ui-core-ship-form-field.mjs +310 -0
- package/fesm2022/ship-ui-core-ship-form-field.mjs.map +1 -0
- package/fesm2022/ship-ui-core-ship-icon.mjs +81 -0
- package/fesm2022/ship-ui-core-ship-icon.mjs.map +1 -0
- package/fesm2022/ship-ui-core-ship-list.mjs +22 -0
- package/fesm2022/ship-ui-core-ship-list.mjs.map +1 -0
- package/fesm2022/ship-ui-core-ship-menu.mjs +545 -0
- package/fesm2022/ship-ui-core-ship-menu.mjs.map +1 -0
- package/fesm2022/ship-ui-core-ship-popover.mjs +286 -0
- package/fesm2022/ship-ui-core-ship-popover.mjs.map +1 -0
- package/fesm2022/ship-ui-core-ship-progress-bar.mjs +37 -0
- package/fesm2022/ship-ui-core-ship-progress-bar.mjs.map +1 -0
- package/fesm2022/ship-ui-core-ship-radio.mjs +102 -0
- package/fesm2022/ship-ui-core-ship-radio.mjs.map +1 -0
- package/fesm2022/ship-ui-core-ship-range-slider.mjs +277 -0
- package/fesm2022/ship-ui-core-ship-range-slider.mjs.map +1 -0
- package/fesm2022/ship-ui-core-ship-select.mjs +971 -0
- package/fesm2022/ship-ui-core-ship-select.mjs.map +1 -0
- package/fesm2022/ship-ui-core-ship-sidenav.mjs +248 -0
- package/fesm2022/ship-ui-core-ship-sidenav.mjs.map +1 -0
- package/fesm2022/ship-ui-core-ship-sortable.mjs +485 -0
- package/fesm2022/ship-ui-core-ship-sortable.mjs.map +1 -0
- package/fesm2022/ship-ui-core-ship-spinner.mjs +28 -0
- package/fesm2022/ship-ui-core-ship-spinner.mjs.map +1 -0
- package/fesm2022/ship-ui-core-ship-stepper.mjs +76 -0
- package/fesm2022/ship-ui-core-ship-stepper.mjs.map +1 -0
- package/fesm2022/ship-ui-core-ship-table-filter-bar.mjs +28 -0
- package/fesm2022/ship-ui-core-ship-table-filter-bar.mjs.map +1 -0
- package/fesm2022/ship-ui-core-ship-table.mjs +442 -0
- package/fesm2022/ship-ui-core-ship-table.mjs.map +1 -0
- package/fesm2022/ship-ui-core-ship-tabs.mjs +38 -0
- package/fesm2022/ship-ui-core-ship-tabs.mjs.map +1 -0
- package/fesm2022/ship-ui-core-ship-theme-toggle.mjs +119 -0
- package/fesm2022/ship-ui-core-ship-theme-toggle.mjs.map +1 -0
- package/fesm2022/ship-ui-core-ship-toggle-card.mjs +75 -0
- package/fesm2022/ship-ui-core-ship-toggle-card.mjs.map +1 -0
- package/fesm2022/ship-ui-core-ship-toggle.mjs +105 -0
- package/fesm2022/ship-ui-core-ship-toggle.mjs.map +1 -0
- package/fesm2022/ship-ui-core-ship-virtual-scroll.mjs +186 -0
- package/fesm2022/ship-ui-core-ship-virtual-scroll.mjs.map +1 -0
- package/fesm2022/ship-ui-core.mjs +880 -8782
- package/fesm2022/ship-ui-core.mjs.map +1 -1
- package/package.json +147 -3
- package/styles/core.scss +43 -0
- package/styles/helpers.scss +2 -0
- package/styles/index.scss +12 -123
- package/types/ship-ui-core-sh-form-field-experimental.d.ts +11 -0
- package/types/ship-ui-core-ship-accordion.d.ts +19 -0
- package/types/ship-ui-core-ship-alert.d.ts +68 -0
- package/types/ship-ui-core-ship-blueprint.d.ts +112 -0
- package/types/ship-ui-core-ship-button-group.d.ts +15 -0
- package/types/ship-ui-core-ship-button.d.ts +13 -0
- package/types/ship-ui-core-ship-card.d.ts +11 -0
- package/types/ship-ui-core-ship-checkbox.d.ts +22 -0
- package/types/ship-ui-core-ship-chip.d.ts +15 -0
- package/types/ship-ui-core-ship-color-picker.d.ts +105 -0
- package/types/ship-ui-core-ship-datepicker.d.ts +96 -0
- package/types/ship-ui-core-ship-dialog.d.ts +76 -0
- package/types/ship-ui-core-ship-divider.d.ts +8 -0
- package/types/ship-ui-core-ship-event-card.d.ts +11 -0
- package/types/ship-ui-core-ship-file-upload.d.ts +20 -0
- package/types/ship-ui-core-ship-form-field.d.ts +32 -0
- package/types/ship-ui-core-ship-icon.d.ts +18 -0
- package/types/ship-ui-core-ship-list.d.ts +8 -0
- package/types/ship-ui-core-ship-menu.d.ts +49 -0
- package/types/ship-ui-core-ship-popover.d.ts +40 -0
- package/types/ship-ui-core-ship-progress-bar.d.ts +14 -0
- package/types/ship-ui-core-ship-radio.d.ts +22 -0
- package/types/ship-ui-core-ship-range-slider.d.ts +31 -0
- package/types/ship-ui-core-ship-select.d.ts +81 -0
- package/types/ship-ui-core-ship-sidenav.d.ts +36 -0
- package/types/ship-ui-core-ship-sortable.d.ts +72 -0
- package/types/ship-ui-core-ship-spinner.d.ts +10 -0
- package/types/ship-ui-core-ship-stepper.d.ts +13 -0
- package/types/ship-ui-core-ship-table-filter-bar.d.ts +8 -0
- package/types/ship-ui-core-ship-table.d.ts +69 -0
- package/types/ship-ui-core-ship-tabs.d.ts +14 -0
- package/types/ship-ui-core-ship-theme-toggle.d.ts +28 -0
- package/types/ship-ui-core-ship-toggle-card.d.ts +15 -0
- package/types/ship-ui-core-ship-toggle.d.ts +21 -0
- package/types/ship-ui-core-ship-virtual-scroll.d.ts +22 -0
- package/types/ship-ui-core.d.ts +88 -1070
- package/styles/components/ship-accordion.scss +0 -113
- package/styles/components/ship-alert-container.scss +0 -49
- package/styles/components/ship-alert.scss +0 -177
- package/styles/components/ship-blueprint.scss +0 -242
- package/styles/components/ship-button-group.scss +0 -165
- package/styles/components/ship-button.scss +0 -141
- package/styles/components/ship-card.scss +0 -57
- package/styles/components/ship-checkbox.scss +0 -116
- package/styles/components/ship-chip.scss +0 -104
- package/styles/components/ship-color-picker.scss +0 -150
- package/styles/components/ship-datepicker.scss +0 -317
- package/styles/components/ship-dialog.scss +0 -152
- package/styles/components/ship-divider.scss +0 -27
- package/styles/components/ship-event-card.scss +0 -51
- package/styles/components/ship-file-upload.scss +0 -47
- package/styles/components/ship-form-field.scss +0 -408
- package/styles/components/ship-icon.scss +0 -54
- package/styles/components/ship-list.scss +0 -165
- package/styles/components/ship-menu.scss +0 -237
- package/styles/components/ship-popover.scss +0 -205
- package/styles/components/ship-progress-bar.scss +0 -173
- package/styles/components/ship-radio.scss +0 -113
- package/styles/components/ship-range-slider.scss +0 -421
- package/styles/components/ship-select.scss +0 -153
- package/styles/components/ship-sidenav.scss +0 -195
- package/styles/components/ship-sortable.scss +0 -45
- package/styles/components/ship-spinner.scss +0 -53
- package/styles/components/ship-stepper.scss +0 -158
- package/styles/components/ship-table.scss +0 -443
- package/styles/components/ship-tabs.scss +0 -125
- package/styles/components/ship-theme-toggle.scss +0 -41
- package/styles/components/ship-toggle-card.scss +0 -69
- package/styles/components/ship-toggle.scss +0 -255
- package/styles/components/ship-tooltip.scss +0 -151
- package/styles/components/ship-virtual-scroll.scss +0 -12
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { inject, ChangeDetectorRef, Renderer2, ElementRef, viewChild, viewChildren, signal, computed, effect, ChangeDetectionStrategy, ViewEncapsulation, Component } from '@angular/core';
|
|
3
|
+
|
|
4
|
+
class ShipVirtualScroll {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.#changeRef = inject(ChangeDetectorRef);
|
|
7
|
+
this.#renderer = inject(Renderer2);
|
|
8
|
+
this.#hostElement = inject(ElementRef);
|
|
9
|
+
this.viewportRef = viewChild.required('viewport');
|
|
10
|
+
this.itemElements = viewChildren('item', /* @ts-ignore */
|
|
11
|
+
...(ngDevMode ? [{ debugName: "itemElements" }] : /* istanbul ignore next */ []));
|
|
12
|
+
this.bufferSize = signal(10, /* @ts-ignore */
|
|
13
|
+
...(ngDevMode ? [{ debugName: "bufferSize" }] : /* istanbul ignore next */ []));
|
|
14
|
+
this.itemHeights = signal([], /* @ts-ignore */
|
|
15
|
+
...(ngDevMode ? [{ debugName: "itemHeights" }] : /* istanbul ignore next */ []));
|
|
16
|
+
this.startIndex = signal(0, /* @ts-ignore */
|
|
17
|
+
...(ngDevMode ? [{ debugName: "startIndex" }] : /* istanbul ignore next */ []));
|
|
18
|
+
this.endIndex = signal(0, /* @ts-ignore */
|
|
19
|
+
...(ngDevMode ? [{ debugName: "endIndex" }] : /* istanbul ignore next */ []));
|
|
20
|
+
this.translateY = signal(0, /* @ts-ignore */
|
|
21
|
+
...(ngDevMode ? [{ debugName: "translateY" }] : /* istanbul ignore next */ []));
|
|
22
|
+
this.totalHeight = computed(() => this.itemHeights().reduce((sum, height) => sum + height, 0), /* @ts-ignore */
|
|
23
|
+
...(ngDevMode ? [{ debugName: "totalHeight" }] : /* istanbul ignore next */ []));
|
|
24
|
+
this.numberOfRenderedItems = signal(0, /* @ts-ignore */
|
|
25
|
+
...(ngDevMode ? [{ debugName: "numberOfRenderedItems" }] : /* istanbul ignore next */ []));
|
|
26
|
+
this.#resizeObserver = null;
|
|
27
|
+
this.#hostResizeObserver = null;
|
|
28
|
+
this.#itemHeightsEffect = effect(() => {
|
|
29
|
+
const startIndex = this.startIndex();
|
|
30
|
+
const endIndex = this.endIndex();
|
|
31
|
+
const itemHeights = this.itemHeights();
|
|
32
|
+
if (startIndex > 0 && endIndex > 0 && itemHeights.length > 0) {
|
|
33
|
+
let newTranslateY = 0;
|
|
34
|
+
for (let i = 0; i < startIndex; i++) {
|
|
35
|
+
newTranslateY += itemHeights[i];
|
|
36
|
+
}
|
|
37
|
+
this.translateY.set(newTranslateY);
|
|
38
|
+
}
|
|
39
|
+
}, /* @ts-ignore */
|
|
40
|
+
...(ngDevMode ? [{ debugName: "#itemHeightsEffect" }] : /* istanbul ignore next */ []));
|
|
41
|
+
this.#totalHeightEffect = effect(() => {
|
|
42
|
+
const _ = this.totalHeight();
|
|
43
|
+
this.#changeRef.detectChanges();
|
|
44
|
+
}, /* @ts-ignore */
|
|
45
|
+
...(ngDevMode ? [{ debugName: "#totalHeightEffect" }] : /* istanbul ignore next */ []));
|
|
46
|
+
this.#itemElementsEffect = effect(() => {
|
|
47
|
+
const itemElements = this.itemElements();
|
|
48
|
+
if (this.#resizeObserver && itemElements) {
|
|
49
|
+
this.#resizeObserver.disconnect();
|
|
50
|
+
const heights = new Array(itemElements.length).fill(0);
|
|
51
|
+
this.numberOfRenderedItems.set(itemElements.length);
|
|
52
|
+
this.itemHeights.set(heights);
|
|
53
|
+
for (let i = 0; i < itemElements.length; i++) {
|
|
54
|
+
this.#resizeObserver.observe(itemElements[i].nativeElement);
|
|
55
|
+
heights[i] = itemElements[i].nativeElement.offsetHeight;
|
|
56
|
+
}
|
|
57
|
+
this.itemHeights.set(heights);
|
|
58
|
+
this.#calculateVisibleItems();
|
|
59
|
+
}
|
|
60
|
+
}, /* @ts-ignore */
|
|
61
|
+
...(ngDevMode ? [{ debugName: "#itemElementsEffect" }] : /* istanbul ignore next */ []));
|
|
62
|
+
}
|
|
63
|
+
#changeRef;
|
|
64
|
+
#renderer;
|
|
65
|
+
#hostElement;
|
|
66
|
+
#resizeObserver;
|
|
67
|
+
#hostResizeObserver;
|
|
68
|
+
#itemHeightsEffect;
|
|
69
|
+
#totalHeightEffect;
|
|
70
|
+
#itemElementsEffect;
|
|
71
|
+
ngAfterViewInit() {
|
|
72
|
+
this.#setupHostResizeObserver();
|
|
73
|
+
this.#setupResizeObserver();
|
|
74
|
+
this.#changeRef.detectChanges();
|
|
75
|
+
}
|
|
76
|
+
onScroll() {
|
|
77
|
+
this.#calculateVisibleItems();
|
|
78
|
+
}
|
|
79
|
+
#setupHostResizeObserver() {
|
|
80
|
+
if (typeof ResizeObserver === 'undefined')
|
|
81
|
+
return;
|
|
82
|
+
this.#hostResizeObserver = new ResizeObserver((entries) => {
|
|
83
|
+
const hostElement = entries[0];
|
|
84
|
+
if (hostElement) {
|
|
85
|
+
const newHeight = hostElement.contentRect.height;
|
|
86
|
+
this.#renderer.setStyle(this.viewportRef().nativeElement, 'height', `${newHeight}px`);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
this.#hostResizeObserver.observe(this.#hostElement.nativeElement);
|
|
90
|
+
}
|
|
91
|
+
#setupResizeObserver() {
|
|
92
|
+
if (typeof ResizeObserver === 'undefined')
|
|
93
|
+
return;
|
|
94
|
+
this.#resizeObserver = new ResizeObserver((entries) => {
|
|
95
|
+
const newHeights = [...this.itemHeights()];
|
|
96
|
+
let didUpdate = false;
|
|
97
|
+
for (const entry of entries) {
|
|
98
|
+
const index = this.itemElements().findIndex((el) => el.nativeElement === entry.target);
|
|
99
|
+
if (index !== undefined && index !== -1) {
|
|
100
|
+
const newHeight = entry.contentRect.height;
|
|
101
|
+
if (newHeights[index] !== newHeight) {
|
|
102
|
+
newHeights[index] = newHeight;
|
|
103
|
+
didUpdate = true;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (didUpdate) {
|
|
108
|
+
this.itemHeights.set(newHeights);
|
|
109
|
+
this.#calculateVisibleItems();
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
#cleanupResizeObserver() {
|
|
114
|
+
if (this.#resizeObserver) {
|
|
115
|
+
this.#resizeObserver.disconnect();
|
|
116
|
+
this.#resizeObserver = null;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
#cleanupHostResizeObserver() {
|
|
120
|
+
if (this.#hostResizeObserver) {
|
|
121
|
+
this.#hostResizeObserver.disconnect();
|
|
122
|
+
this.#hostResizeObserver = null;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
#calculateVisibleItems() {
|
|
126
|
+
const nativeElement = this.viewportRef();
|
|
127
|
+
if (!nativeElement)
|
|
128
|
+
return;
|
|
129
|
+
const scrollTop = nativeElement.nativeElement.scrollTop;
|
|
130
|
+
const viewportHeight = nativeElement.nativeElement.clientHeight;
|
|
131
|
+
let accumulatedHeight = 0;
|
|
132
|
+
let startIndex = -1;
|
|
133
|
+
let endIndex = -1;
|
|
134
|
+
for (let i = 0; i < this.itemHeights().length; i++) {
|
|
135
|
+
const itemHeight = this.itemHeights()[i];
|
|
136
|
+
if (startIndex === -1 && accumulatedHeight + itemHeight >= scrollTop - this.bufferSize()) {
|
|
137
|
+
startIndex = i;
|
|
138
|
+
}
|
|
139
|
+
if (endIndex === -1 && accumulatedHeight >= scrollTop + viewportHeight + this.bufferSize()) {
|
|
140
|
+
endIndex = i;
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
accumulatedHeight += itemHeight;
|
|
144
|
+
}
|
|
145
|
+
if (endIndex === -1) {
|
|
146
|
+
endIndex = this.itemHeights().length - 1;
|
|
147
|
+
}
|
|
148
|
+
if (this.startIndex() !== startIndex) {
|
|
149
|
+
this.startIndex.set(startIndex);
|
|
150
|
+
}
|
|
151
|
+
if (this.endIndex() !== endIndex) {
|
|
152
|
+
this.endIndex.set(endIndex);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
ngOnDestroy() {
|
|
156
|
+
this.#cleanupResizeObserver();
|
|
157
|
+
this.#cleanupHostResizeObserver();
|
|
158
|
+
}
|
|
159
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: ShipVirtualScroll, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
160
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.0.0", type: ShipVirtualScroll, isStandalone: true, selector: "sh-virtual-scroll", viewQueries: [{ propertyName: "viewportRef", first: true, predicate: ["viewport"], descendants: true, isSignal: true }, { propertyName: "itemElements", predicate: ["item"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
161
|
+
<div class="viewport" #viewport (scroll)="onScroll()">
|
|
162
|
+
<div class="total-height" [style.height]="totalHeight() + 'px'"></div>
|
|
163
|
+
<div class="items-container" [style.transform]="'translateY(' + translateY() + 'px)'">
|
|
164
|
+
<ng-content />
|
|
165
|
+
</div>
|
|
166
|
+
</div>
|
|
167
|
+
`, isInline: true, styles: ["sh-virtual-scroll{overflow-y:auto;position:relative;display:block;height:600px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
168
|
+
}
|
|
169
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: ShipVirtualScroll, decorators: [{
|
|
170
|
+
type: Component,
|
|
171
|
+
args: [{ selector: 'sh-virtual-scroll', encapsulation: ViewEncapsulation.None, imports: [], template: `
|
|
172
|
+
<div class="viewport" #viewport (scroll)="onScroll()">
|
|
173
|
+
<div class="total-height" [style.height]="totalHeight() + 'px'"></div>
|
|
174
|
+
<div class="items-container" [style.transform]="'translateY(' + translateY() + 'px)'">
|
|
175
|
+
<ng-content />
|
|
176
|
+
</div>
|
|
177
|
+
</div>
|
|
178
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["sh-virtual-scroll{overflow-y:auto;position:relative;display:block;height:600px}\n"] }]
|
|
179
|
+
}], propDecorators: { viewportRef: [{ type: i0.ViewChild, args: ['viewport', { isSignal: true }] }], itemElements: [{ type: i0.ViewChildren, args: ['item', { isSignal: true }] }] } });
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Generated bundle index. Do not edit.
|
|
183
|
+
*/
|
|
184
|
+
|
|
185
|
+
export { ShipVirtualScroll };
|
|
186
|
+
//# sourceMappingURL=ship-ui-core-ship-virtual-scroll.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ship-ui-core-ship-virtual-scroll.mjs","sources":["../../../projects/ship-ui/ship-virtual-scroll/ship-virtual-scroll.component.ts","../../../projects/ship-ui/ship-virtual-scroll/ship-ui-core-ship-virtual-scroll.ts"],"sourcesContent":["import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, effect, ElementRef, inject, Renderer2, signal, viewChild, viewChildren, ViewEncapsulation } from '@angular/core';\n\n@Component({\n selector: 'sh-virtual-scroll',\n styleUrl: './ship-virtual-scroll.scss',\n encapsulation: ViewEncapsulation.None,\n imports: [],\n template: `\n <div class=\"viewport\" #viewport (scroll)=\"onScroll()\">\n <div class=\"total-height\" [style.height]=\"totalHeight() + 'px'\"></div>\n <div class=\"items-container\" [style.transform]=\"'translateY(' + translateY() + 'px)'\">\n <ng-content />\n </div>\n </div>\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ShipVirtualScroll {\n #changeRef = inject(ChangeDetectorRef);\n #renderer = inject(Renderer2);\n #hostElement = inject(ElementRef);\n\n viewportRef = viewChild.required<ElementRef<HTMLDivElement>>('viewport');\n itemElements = viewChildren<ElementRef>('item');\n\n bufferSize = signal(10);\n\n itemHeights = signal<number[]>([]);\n startIndex = signal(0);\n endIndex = signal(0);\n translateY = signal(0);\n totalHeight = computed(() => this.itemHeights().reduce((sum, height) => sum + height, 0));\n numberOfRenderedItems = signal(0);\n\n #resizeObserver: ResizeObserver | null = null;\n #hostResizeObserver: ResizeObserver | null = null;\n\n #itemHeightsEffect = effect(() => {\n const startIndex = this.startIndex();\n const endIndex = this.endIndex();\n const itemHeights = this.itemHeights();\n\n if (startIndex > 0 && endIndex > 0 && itemHeights.length > 0) {\n let newTranslateY = 0;\n for (let i = 0; i < startIndex; i++) {\n newTranslateY += itemHeights[i];\n }\n this.translateY.set(newTranslateY);\n }\n });\n\n #totalHeightEffect = effect(() => {\n const _ = this.totalHeight();\n this.#changeRef.detectChanges();\n });\n\n #itemElementsEffect = effect(() => {\n const itemElements = this.itemElements();\n\n if (this.#resizeObserver && itemElements) {\n this.#resizeObserver.disconnect();\n const heights = new Array(itemElements.length).fill(0);\n this.numberOfRenderedItems.set(itemElements.length);\n this.itemHeights.set(heights);\n\n for (let i = 0; i < itemElements.length; i++) {\n this.#resizeObserver.observe(itemElements[i].nativeElement);\n heights[i] = itemElements[i].nativeElement.offsetHeight;\n }\n\n this.itemHeights.set(heights);\n this.#calculateVisibleItems();\n }\n });\n\n ngAfterViewInit() {\n this.#setupHostResizeObserver();\n this.#setupResizeObserver();\n this.#changeRef.detectChanges();\n }\n\n onScroll() {\n this.#calculateVisibleItems();\n }\n\n #setupHostResizeObserver() {\n if (typeof ResizeObserver === 'undefined') return;\n this.#hostResizeObserver = new ResizeObserver((entries) => {\n const hostElement = entries[0];\n if (hostElement) {\n const newHeight = hostElement.contentRect.height;\n this.#renderer.setStyle(this.viewportRef().nativeElement, 'height', `${newHeight}px`);\n }\n });\n\n this.#hostResizeObserver.observe(this.#hostElement.nativeElement);\n }\n\n #setupResizeObserver() {\n if (typeof ResizeObserver === 'undefined') return;\n this.#resizeObserver = new ResizeObserver((entries) => {\n const newHeights = [...this.itemHeights()];\n\n let didUpdate = false;\n\n for (const entry of entries) {\n const index = this.itemElements().findIndex((el) => el.nativeElement === entry.target);\n\n if (index !== undefined && index !== -1) {\n const newHeight = entry.contentRect.height;\n if (newHeights[index] !== newHeight) {\n newHeights[index] = newHeight;\n didUpdate = true;\n }\n }\n }\n\n if (didUpdate) {\n this.itemHeights.set(newHeights);\n this.#calculateVisibleItems();\n }\n });\n }\n\n #cleanupResizeObserver() {\n if (this.#resizeObserver) {\n this.#resizeObserver.disconnect();\n this.#resizeObserver = null;\n }\n }\n\n #cleanupHostResizeObserver() {\n if (this.#hostResizeObserver) {\n this.#hostResizeObserver.disconnect();\n this.#hostResizeObserver = null;\n }\n }\n\n #calculateVisibleItems() {\n const nativeElement = this.viewportRef();\n if (!nativeElement) return;\n\n const scrollTop = nativeElement.nativeElement.scrollTop;\n const viewportHeight = nativeElement.nativeElement.clientHeight;\n\n let accumulatedHeight = 0;\n let startIndex = -1;\n let endIndex = -1;\n\n for (let i = 0; i < this.itemHeights().length; i++) {\n const itemHeight = this.itemHeights()[i];\n\n if (startIndex === -1 && accumulatedHeight + itemHeight >= scrollTop - this.bufferSize()) {\n startIndex = i;\n }\n\n if (endIndex === -1 && accumulatedHeight >= scrollTop + viewportHeight + this.bufferSize()) {\n endIndex = i;\n break;\n }\n\n accumulatedHeight += itemHeight;\n }\n\n if (endIndex === -1) {\n endIndex = this.itemHeights().length - 1;\n }\n\n if (this.startIndex() !== startIndex) {\n this.startIndex.set(startIndex);\n }\n if (this.endIndex() !== endIndex) {\n this.endIndex.set(endIndex);\n }\n }\n\n ngOnDestroy() {\n this.#cleanupResizeObserver();\n this.#cleanupHostResizeObserver();\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|