mtrl-addons 0.2.2 → 0.2.4
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/{src/components/index.ts → dist/components/index.d.ts} +0 -2
- package/dist/components/vlist/config.d.ts +86 -0
- package/{src/components/vlist/constants.ts → dist/components/vlist/constants.d.ts} +10 -11
- package/dist/components/vlist/features/api.d.ts +7 -0
- package/{src/components/vlist/features/index.ts → dist/components/vlist/features/index.d.ts} +0 -2
- package/dist/components/vlist/features/selection.d.ts +6 -0
- package/dist/components/vlist/features/viewport.d.ts +9 -0
- package/dist/components/vlist/features.d.ts +31 -0
- package/{src/components/vlist/index.ts → dist/components/vlist/index.d.ts} +1 -10
- package/dist/components/vlist/types.d.ts +596 -0
- package/dist/components/vlist/vlist.d.ts +29 -0
- package/dist/core/compose/features/gestures/index.d.ts +86 -0
- package/dist/core/compose/features/gestures/longpress.d.ts +85 -0
- package/dist/core/compose/features/gestures/pan.d.ts +108 -0
- package/dist/core/compose/features/gestures/pinch.d.ts +111 -0
- package/dist/core/compose/features/gestures/rotate.d.ts +111 -0
- package/dist/core/compose/features/gestures/swipe.d.ts +149 -0
- package/dist/core/compose/features/gestures/tap.d.ts +79 -0
- package/{src/core/compose/features/index.ts → dist/core/compose/features/index.d.ts} +1 -2
- package/{src/core/compose/index.ts → dist/core/compose/index.d.ts} +2 -11
- package/{src/core/gestures/index.ts → dist/core/gestures/index.d.ts} +1 -20
- package/dist/core/gestures/longpress.d.ts +23 -0
- package/dist/core/gestures/manager.d.ts +14 -0
- package/dist/core/gestures/pan.d.ts +12 -0
- package/dist/core/gestures/pinch.d.ts +14 -0
- package/dist/core/gestures/rotate.d.ts +14 -0
- package/dist/core/gestures/swipe.d.ts +20 -0
- package/dist/core/gestures/tap.d.ts +12 -0
- package/dist/core/gestures/types.d.ts +320 -0
- package/dist/core/gestures/utils.d.ts +57 -0
- package/dist/core/index.d.ts +13 -0
- package/dist/core/layout/config.d.ts +33 -0
- package/dist/core/layout/index.d.ts +51 -0
- package/dist/core/layout/jsx.d.ts +65 -0
- package/dist/core/layout/schema.d.ts +112 -0
- package/dist/core/layout/types.d.ts +69 -0
- package/dist/core/viewport/constants.d.ts +105 -0
- package/dist/core/viewport/features/base.d.ts +14 -0
- package/dist/core/viewport/features/collection.d.ts +41 -0
- package/dist/core/viewport/features/events.d.ts +13 -0
- package/{src/core/viewport/features/index.ts → dist/core/viewport/features/index.d.ts} +0 -7
- package/dist/core/viewport/features/item-size.d.ts +30 -0
- package/dist/core/viewport/features/loading.d.ts +34 -0
- package/dist/core/viewport/features/momentum.d.ts +17 -0
- package/dist/core/viewport/features/performance.d.ts +53 -0
- package/dist/core/viewport/features/placeholders.d.ts +38 -0
- package/dist/core/viewport/features/rendering.d.ts +16 -0
- package/dist/core/viewport/features/scrollbar.d.ts +26 -0
- package/dist/core/viewport/features/scrolling.d.ts +16 -0
- package/dist/core/viewport/features/utils.d.ts +43 -0
- package/dist/core/viewport/features/virtual.d.ts +18 -0
- package/{src/core/viewport/index.ts → dist/core/viewport/index.d.ts} +1 -17
- package/dist/core/viewport/types.d.ts +96 -0
- package/dist/core/viewport/utils/speed-tracker.d.ts +22 -0
- package/dist/core/viewport/viewport.d.ts +11 -0
- package/{src/index.ts → dist/index.d.ts} +0 -4
- package/dist/index.js +5143 -0
- package/dist/index.mjs +5111 -0
- package/dist/styles.css +254 -0
- package/dist/styles.css.map +1 -0
- package/package.json +16 -2
- package/.cursorrules +0 -117
- package/AI.md +0 -39
- package/CLAUDE.md +0 -882
- package/build.js +0 -377
- package/index.ts +0 -7
- package/scripts/analyze-orphaned-functions.ts +0 -387
- package/scripts/debug/vlist-selection.ts +0 -121
- package/src/components/vlist/config.ts +0 -323
- package/src/components/vlist/features/api.ts +0 -626
- package/src/components/vlist/features/selection.ts +0 -436
- package/src/components/vlist/features/viewport.ts +0 -59
- package/src/components/vlist/features.ts +0 -112
- package/src/components/vlist/types.ts +0 -723
- package/src/components/vlist/vlist.ts +0 -92
- package/src/core/compose/features/gestures/index.ts +0 -227
- package/src/core/compose/features/gestures/longpress.ts +0 -383
- package/src/core/compose/features/gestures/pan.ts +0 -424
- package/src/core/compose/features/gestures/pinch.ts +0 -475
- package/src/core/compose/features/gestures/rotate.ts +0 -485
- package/src/core/compose/features/gestures/swipe.ts +0 -492
- package/src/core/compose/features/gestures/tap.ts +0 -334
- package/src/core/gestures/longpress.ts +0 -68
- package/src/core/gestures/manager.ts +0 -418
- package/src/core/gestures/pan.ts +0 -48
- package/src/core/gestures/pinch.ts +0 -58
- package/src/core/gestures/rotate.ts +0 -58
- package/src/core/gestures/swipe.ts +0 -66
- package/src/core/gestures/tap.ts +0 -45
- package/src/core/gestures/types.ts +0 -387
- package/src/core/gestures/utils.ts +0 -128
- package/src/core/index.ts +0 -43
- package/src/core/layout/config.ts +0 -102
- package/src/core/layout/index.ts +0 -168
- package/src/core/layout/jsx.ts +0 -174
- package/src/core/layout/schema.ts +0 -1044
- package/src/core/layout/types.ts +0 -95
- package/src/core/viewport/constants.ts +0 -145
- package/src/core/viewport/features/base.ts +0 -73
- package/src/core/viewport/features/collection.ts +0 -1182
- package/src/core/viewport/features/events.ts +0 -130
- package/src/core/viewport/features/item-size.ts +0 -271
- package/src/core/viewport/features/loading.ts +0 -263
- package/src/core/viewport/features/momentum.ts +0 -269
- package/src/core/viewport/features/performance.ts +0 -161
- package/src/core/viewport/features/placeholders.ts +0 -335
- package/src/core/viewport/features/rendering.ts +0 -962
- package/src/core/viewport/features/scrollbar.ts +0 -434
- package/src/core/viewport/features/scrolling.ts +0 -634
- package/src/core/viewport/features/utils.ts +0 -94
- package/src/core/viewport/features/virtual.ts +0 -525
- package/src/core/viewport/types.ts +0 -133
- package/src/core/viewport/utils/speed-tracker.ts +0 -79
- package/src/core/viewport/viewport.ts +0 -265
- package/test/benchmarks/layout/advanced.test.ts +0 -656
- package/test/benchmarks/layout/comparison.test.ts +0 -519
- package/test/benchmarks/layout/performance-comparison.test.ts +0 -274
- package/test/benchmarks/layout/real-components.test.ts +0 -733
- package/test/benchmarks/layout/simple.test.ts +0 -321
- package/test/benchmarks/layout/stress.test.ts +0 -990
- package/test/collection/basic.test.ts +0 -304
- package/test/components/vlist-selection.test.ts +0 -240
- package/test/components/vlist.test.ts +0 -63
- package/test/core/collection/adapter.test.ts +0 -161
- package/test/core/collection/collection.test.ts +0 -394
- package/test/core/layout/layout.test.ts +0 -201
- package/test/utils/dom-helpers.ts +0 -275
- package/test/utils/performance-helpers.ts +0 -392
- package/tsconfig.json +0 -20
|
@@ -1,434 +0,0 @@
|
|
|
1
|
-
// src/core/viewport/features/scrollbar.ts
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Scrollbar Feature - Custom scrollbar implementation
|
|
5
|
-
* Provides visual scroll indication and drag-to-scroll functionality
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import type { ViewportContext, ViewportComponent } from "../types";
|
|
9
|
-
import { VIEWPORT_CONSTANTS } from "../constants";
|
|
10
|
-
import { wrapInitialize, wrapDestroy, storeFeatureFunction } from "./utils";
|
|
11
|
-
import { PREFIX, addClass, removeClass } from "mtrl";
|
|
12
|
-
|
|
13
|
-
export interface ScrollbarConfig {
|
|
14
|
-
enabled?: boolean;
|
|
15
|
-
autoHide?: boolean;
|
|
16
|
-
thumbMinHeight?: number;
|
|
17
|
-
thumbColor?: string;
|
|
18
|
-
trackColor?: string;
|
|
19
|
-
borderRadius?: number;
|
|
20
|
-
fadeTimeout?: number;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface ScrollbarComponent {
|
|
24
|
-
scrollbar: {
|
|
25
|
-
show: () => void;
|
|
26
|
-
hide: () => void;
|
|
27
|
-
updateBounds: (totalVirtualSize: number, containerSize: number) => void;
|
|
28
|
-
updatePosition: (scrollPosition: number) => void;
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Adds scrollbar functionality to viewport component
|
|
34
|
-
*/
|
|
35
|
-
export function withScrollbar(config: ScrollbarConfig = {}) {
|
|
36
|
-
return <T extends ViewportContext & ViewportComponent>(
|
|
37
|
-
component: T
|
|
38
|
-
): T & ScrollbarComponent => {
|
|
39
|
-
const {
|
|
40
|
-
enabled = true,
|
|
41
|
-
autoHide = true,
|
|
42
|
-
thumbMinHeight = 25,
|
|
43
|
-
borderRadius = 4,
|
|
44
|
-
fadeTimeout = 1000,
|
|
45
|
-
} = config;
|
|
46
|
-
|
|
47
|
-
// Return no-op if disabled
|
|
48
|
-
if (!enabled) {
|
|
49
|
-
return {
|
|
50
|
-
...component,
|
|
51
|
-
scrollbar: {
|
|
52
|
-
show: () => {},
|
|
53
|
-
hide: () => {},
|
|
54
|
-
updateBounds: () => {},
|
|
55
|
-
updatePosition: () => {},
|
|
56
|
-
},
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// State
|
|
61
|
-
let viewportElement: HTMLElement | null = null;
|
|
62
|
-
let scrollbarTrack: HTMLElement | null = null;
|
|
63
|
-
let scrollbarThumb: HTMLElement | null = null;
|
|
64
|
-
let isInitialized = false;
|
|
65
|
-
let isDragging = false;
|
|
66
|
-
let dragStartY = 0;
|
|
67
|
-
let dragStartScrollPosition = 0;
|
|
68
|
-
let hideTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
69
|
-
let totalVirtualSize = 0;
|
|
70
|
-
let containerSize = 0;
|
|
71
|
-
let thumbHeight = 0;
|
|
72
|
-
let animationFrameId: number | null = null;
|
|
73
|
-
let lastRequestedScrollPosition: number | null = null;
|
|
74
|
-
let isCursorMode = false;
|
|
75
|
-
let loadedItemsCount = 0;
|
|
76
|
-
|
|
77
|
-
// Create scrollbar elements
|
|
78
|
-
const createScrollbarElements = () => {
|
|
79
|
-
if (!viewportElement) return;
|
|
80
|
-
|
|
81
|
-
scrollbarTrack = document.createElement("div");
|
|
82
|
-
addClass(scrollbarTrack, VIEWPORT_CONSTANTS.SCROLLBAR.CLASSES.SCROLLBAR);
|
|
83
|
-
scrollbarTrack.style.cssText = `
|
|
84
|
-
position: absolute;
|
|
85
|
-
top: 0;
|
|
86
|
-
right: 0;
|
|
87
|
-
height: 100%;
|
|
88
|
-
z-index: 10;
|
|
89
|
-
`;
|
|
90
|
-
|
|
91
|
-
scrollbarThumb = document.createElement("div");
|
|
92
|
-
|
|
93
|
-
addClass(
|
|
94
|
-
scrollbarThumb,
|
|
95
|
-
VIEWPORT_CONSTANTS.SCROLLBAR.CLASSES.SCROLLBAR_THUMB
|
|
96
|
-
);
|
|
97
|
-
|
|
98
|
-
scrollbarTrack.appendChild(scrollbarThumb);
|
|
99
|
-
viewportElement.appendChild(scrollbarTrack);
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
// Show/hide functions
|
|
103
|
-
const show = () => {
|
|
104
|
-
if (!scrollbarTrack || totalVirtualSize <= containerSize) return;
|
|
105
|
-
|
|
106
|
-
if (hideTimeout) {
|
|
107
|
-
clearTimeout(hideTimeout);
|
|
108
|
-
hideTimeout = null;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
addClass(
|
|
112
|
-
scrollbarTrack,
|
|
113
|
-
VIEWPORT_CONSTANTS.SCROLLBAR.CLASSES.SCROLLBAR_VISIBLE
|
|
114
|
-
);
|
|
115
|
-
|
|
116
|
-
if (autoHide && !isDragging) {
|
|
117
|
-
hideTimeout = setTimeout(hide, fadeTimeout);
|
|
118
|
-
}
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
const hide = () => {
|
|
122
|
-
if (!scrollbarTrack || isDragging) return;
|
|
123
|
-
removeClass(
|
|
124
|
-
scrollbarTrack,
|
|
125
|
-
VIEWPORT_CONSTANTS.SCROLLBAR.CLASSES.SCROLLBAR_VISIBLE
|
|
126
|
-
);
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
// Update scrollbar bounds
|
|
130
|
-
const updateBounds = (newTotalSize: number, newContainerSize: number) => {
|
|
131
|
-
totalVirtualSize = newTotalSize;
|
|
132
|
-
containerSize = newContainerSize;
|
|
133
|
-
|
|
134
|
-
if (!scrollbarTrack || !scrollbarThumb) return;
|
|
135
|
-
|
|
136
|
-
const needsScrollbar = totalVirtualSize > containerSize;
|
|
137
|
-
// console.log(
|
|
138
|
-
// `[Scrollbar] updateBounds: totalSize=${totalVirtualSize}, containerSize=${containerSize}, needsScrollbar=${needsScrollbar}`
|
|
139
|
-
// );
|
|
140
|
-
scrollbarTrack.style.display = needsScrollbar ? "block" : "none";
|
|
141
|
-
|
|
142
|
-
if (needsScrollbar) {
|
|
143
|
-
let scrollRatio: number;
|
|
144
|
-
|
|
145
|
-
if (isCursorMode && loadedItemsCount > 0) {
|
|
146
|
-
// For cursor mode, thumb size represents loaded content vs estimated total
|
|
147
|
-
// If we don't know total, use loaded items * 2 as estimate
|
|
148
|
-
const estimatedTotal =
|
|
149
|
-
totalVirtualSize > 0 ? totalVirtualSize : loadedItemsCount * 2;
|
|
150
|
-
scrollRatio =
|
|
151
|
-
containerSize /
|
|
152
|
-
Math.max(estimatedTotal, loadedItemsCount + containerSize);
|
|
153
|
-
} else {
|
|
154
|
-
// Normal calculation for offset/page strategies
|
|
155
|
-
scrollRatio = containerSize / totalVirtualSize;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
thumbHeight = Math.max(thumbMinHeight, scrollRatio * containerSize);
|
|
159
|
-
scrollbarThumb.style.height = `${thumbHeight}px`;
|
|
160
|
-
updatePosition(component.viewport?.getScrollPosition() || 0);
|
|
161
|
-
}
|
|
162
|
-
};
|
|
163
|
-
|
|
164
|
-
// Update thumb position
|
|
165
|
-
const updatePosition = (scrollPos: number) => {
|
|
166
|
-
if (!scrollbarThumb || !scrollbarTrack) return;
|
|
167
|
-
|
|
168
|
-
const scrollableDistance = totalVirtualSize - containerSize;
|
|
169
|
-
if (scrollableDistance <= 0) return;
|
|
170
|
-
|
|
171
|
-
const scrollRatio = Math.min(
|
|
172
|
-
1,
|
|
173
|
-
Math.max(0, scrollPos / scrollableDistance)
|
|
174
|
-
);
|
|
175
|
-
const maxThumbPosition =
|
|
176
|
-
scrollbarTrack.clientHeight - scrollbarThumb.clientHeight;
|
|
177
|
-
const thumbPosition = scrollRatio * maxThumbPosition;
|
|
178
|
-
|
|
179
|
-
scrollbarThumb.style.transform = `translateY(${thumbPosition}px)`;
|
|
180
|
-
};
|
|
181
|
-
|
|
182
|
-
// Handle track click
|
|
183
|
-
const handleTrackClick = (e: MouseEvent) => {
|
|
184
|
-
if (!scrollbarTrack || !scrollbarThumb || e.target === scrollbarThumb)
|
|
185
|
-
return;
|
|
186
|
-
|
|
187
|
-
const trackRect = scrollbarTrack.getBoundingClientRect();
|
|
188
|
-
const clickY = e.clientY - trackRect.top;
|
|
189
|
-
const thumbCenterY = clickY - thumbHeight / 2;
|
|
190
|
-
const maxThumbPosition = containerSize - thumbHeight;
|
|
191
|
-
const thumbPosition = Math.max(
|
|
192
|
-
0,
|
|
193
|
-
Math.min(thumbCenterY, maxThumbPosition)
|
|
194
|
-
);
|
|
195
|
-
const scrollRatio = thumbPosition / maxThumbPosition;
|
|
196
|
-
const targetScrollPosition =
|
|
197
|
-
scrollRatio * (totalVirtualSize - containerSize);
|
|
198
|
-
|
|
199
|
-
component.viewport?.scrollToPosition(targetScrollPosition);
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
// Mouse event handlers
|
|
203
|
-
const handleThumbMouseDown = (e: MouseEvent) => {
|
|
204
|
-
e.preventDefault();
|
|
205
|
-
e.stopPropagation();
|
|
206
|
-
|
|
207
|
-
isDragging = true;
|
|
208
|
-
dragStartY = e.clientY;
|
|
209
|
-
dragStartScrollPosition = component.viewport?.getScrollPosition() || 0;
|
|
210
|
-
|
|
211
|
-
if (scrollbarTrack) {
|
|
212
|
-
addClass(
|
|
213
|
-
scrollbarTrack,
|
|
214
|
-
VIEWPORT_CONSTANTS.SCROLLBAR.CLASSES.SCROLLBAR_DRAGGING
|
|
215
|
-
);
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// Emit drag start event to notify viewport
|
|
219
|
-
component.emit?.("viewport:drag-start", {
|
|
220
|
-
source: "scrollbar",
|
|
221
|
-
startPosition: dragStartScrollPosition,
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
document.addEventListener("mousemove", handleMouseMove);
|
|
225
|
-
document.addEventListener("mouseup", handleMouseUp);
|
|
226
|
-
};
|
|
227
|
-
|
|
228
|
-
const handleMouseMove = (e: MouseEvent) => {
|
|
229
|
-
if (!isDragging || !scrollbarTrack || !scrollbarThumb) return;
|
|
230
|
-
|
|
231
|
-
const deltaY = e.clientY - dragStartY;
|
|
232
|
-
const trackHeight = scrollbarTrack.clientHeight;
|
|
233
|
-
const thumbHeight = scrollbarThumb.clientHeight;
|
|
234
|
-
const maxThumbTravel = trackHeight - thumbHeight;
|
|
235
|
-
|
|
236
|
-
if (maxThumbTravel <= 0) return;
|
|
237
|
-
|
|
238
|
-
const deltaRatio = deltaY / maxThumbTravel;
|
|
239
|
-
const dragStartScrollRatio =
|
|
240
|
-
dragStartScrollPosition / (totalVirtualSize - containerSize);
|
|
241
|
-
const newScrollRatio = Math.max(
|
|
242
|
-
0,
|
|
243
|
-
Math.min(1, dragStartScrollRatio + deltaRatio)
|
|
244
|
-
);
|
|
245
|
-
|
|
246
|
-
// Update thumb position immediately
|
|
247
|
-
const thumbPosition = newScrollRatio * maxThumbTravel;
|
|
248
|
-
scrollbarThumb.style.transform = `translateY(${thumbPosition}px)`;
|
|
249
|
-
|
|
250
|
-
// Calculate new scroll position
|
|
251
|
-
const newPosition = newScrollRatio * (totalVirtualSize - containerSize);
|
|
252
|
-
lastRequestedScrollPosition = newPosition;
|
|
253
|
-
|
|
254
|
-
// console.log(
|
|
255
|
-
// `[Scrollbar] Mouse move: newPos=${newPosition.toFixed(
|
|
256
|
-
// 0
|
|
257
|
-
// )}, animationFrameId=${animationFrameId}`
|
|
258
|
-
// );
|
|
259
|
-
|
|
260
|
-
// Throttle viewport updates
|
|
261
|
-
if (animationFrameId === null && component.viewport) {
|
|
262
|
-
animationFrameId = requestAnimationFrame(() => {
|
|
263
|
-
// console.log(
|
|
264
|
-
// `[Scrollbar] RAF callback: scrolling to ${lastRequestedScrollPosition}`
|
|
265
|
-
// );
|
|
266
|
-
if (lastRequestedScrollPosition !== null && component.viewport) {
|
|
267
|
-
component.viewport.scrollToPosition(lastRequestedScrollPosition);
|
|
268
|
-
}
|
|
269
|
-
animationFrameId = null;
|
|
270
|
-
});
|
|
271
|
-
}
|
|
272
|
-
};
|
|
273
|
-
|
|
274
|
-
const handleMouseUp = () => {
|
|
275
|
-
// console.log("[Scrollbar] Mouse up - ending drag");
|
|
276
|
-
isDragging = false;
|
|
277
|
-
|
|
278
|
-
if (animationFrameId !== null) {
|
|
279
|
-
cancelAnimationFrame(animationFrameId);
|
|
280
|
-
animationFrameId = null;
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
if (lastRequestedScrollPosition !== null && component.viewport) {
|
|
284
|
-
component.viewport.scrollToPosition(lastRequestedScrollPosition);
|
|
285
|
-
lastRequestedScrollPosition = null;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
if (scrollbarTrack) {
|
|
289
|
-
removeClass(
|
|
290
|
-
scrollbarTrack,
|
|
291
|
-
VIEWPORT_CONSTANTS.SCROLLBAR.CLASSES.SCROLLBAR_DRAGGING
|
|
292
|
-
);
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
// Emit drag end event
|
|
296
|
-
component.emit?.("viewport:drag-end", {
|
|
297
|
-
source: "scrollbar",
|
|
298
|
-
endPosition: component.viewport?.getScrollPosition() || 0,
|
|
299
|
-
});
|
|
300
|
-
|
|
301
|
-
hide();
|
|
302
|
-
|
|
303
|
-
document.removeEventListener("mousemove", handleMouseMove);
|
|
304
|
-
document.removeEventListener("mouseup", handleMouseUp);
|
|
305
|
-
};
|
|
306
|
-
|
|
307
|
-
// Initialize function
|
|
308
|
-
const initialize = () => {
|
|
309
|
-
if (isInitialized) return;
|
|
310
|
-
|
|
311
|
-
viewportElement = component.element?.querySelector(
|
|
312
|
-
`.${PREFIX}-viewport`
|
|
313
|
-
) as HTMLElement;
|
|
314
|
-
|
|
315
|
-
if (!viewportElement) {
|
|
316
|
-
console.warn("[Scrollbar] No viewport element found");
|
|
317
|
-
return;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
if (
|
|
321
|
-
viewportElement.querySelector(
|
|
322
|
-
`.${PREFIX}-${VIEWPORT_CONSTANTS.SCROLLBAR.CLASSES.SCROLLBAR}`
|
|
323
|
-
)
|
|
324
|
-
)
|
|
325
|
-
return;
|
|
326
|
-
|
|
327
|
-
createScrollbarElements();
|
|
328
|
-
isInitialized = true;
|
|
329
|
-
|
|
330
|
-
if (scrollbarTrack && viewportElement) {
|
|
331
|
-
scrollbarTrack.addEventListener("click", handleTrackClick);
|
|
332
|
-
|
|
333
|
-
if (scrollbarThumb) {
|
|
334
|
-
scrollbarThumb.addEventListener("mousedown", handleThumbMouseDown);
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
viewportElement.addEventListener("mouseenter", show, { passive: true });
|
|
338
|
-
viewportElement.addEventListener(
|
|
339
|
-
"mouseleave",
|
|
340
|
-
() => {
|
|
341
|
-
if (!isDragging) hide();
|
|
342
|
-
},
|
|
343
|
-
{ passive: true }
|
|
344
|
-
);
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
// Initialize with current viewport state
|
|
348
|
-
if (component.viewport) {
|
|
349
|
-
const info = component.viewport.getViewportInfo();
|
|
350
|
-
totalVirtualSize = info.totalVirtualSize;
|
|
351
|
-
containerSize = info.containerSize;
|
|
352
|
-
|
|
353
|
-
// Check if we're in cursor mode
|
|
354
|
-
const collection = (component as any).collection;
|
|
355
|
-
const viewportConfig = (component as any).config;
|
|
356
|
-
isCursorMode = viewportConfig?.pagination?.strategy === "cursor";
|
|
357
|
-
|
|
358
|
-
updateBounds(totalVirtualSize, containerSize);
|
|
359
|
-
updatePosition(component.viewport.getScrollPosition());
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
// Event listeners
|
|
363
|
-
component.on?.("viewport:scroll", (data: any) => {
|
|
364
|
-
if (!isDragging) {
|
|
365
|
-
updatePosition(data.position);
|
|
366
|
-
show();
|
|
367
|
-
}
|
|
368
|
-
});
|
|
369
|
-
|
|
370
|
-
component.on?.("viewport:virtual-size-changed", (data: any) => {
|
|
371
|
-
totalVirtualSize = data.totalVirtualSize;
|
|
372
|
-
updateBounds(data.totalVirtualSize, containerSize);
|
|
373
|
-
});
|
|
374
|
-
|
|
375
|
-
component.on?.("viewport:container-size-changed", (data: any) => {
|
|
376
|
-
containerSize = data.containerSize;
|
|
377
|
-
updateBounds(totalVirtualSize, data.containerSize);
|
|
378
|
-
});
|
|
379
|
-
|
|
380
|
-
// Listen for items loaded to update scrollbar in cursor mode
|
|
381
|
-
component.on?.("viewport:items-changed", (data: any) => {
|
|
382
|
-
if (isCursorMode) {
|
|
383
|
-
loadedItemsCount = data.loadedCount || 0;
|
|
384
|
-
updateBounds(totalVirtualSize, containerSize);
|
|
385
|
-
}
|
|
386
|
-
});
|
|
387
|
-
|
|
388
|
-
// Listen for total items changes (important for cursor mode)
|
|
389
|
-
component.on?.("viewport:total-items-changed", (data: any) => {
|
|
390
|
-
if (isCursorMode && data.total) {
|
|
391
|
-
// In cursor mode, the total is dynamic
|
|
392
|
-
console.log(
|
|
393
|
-
`[Scrollbar] Cursor mode: updating bounds for new total ${data.total}`
|
|
394
|
-
);
|
|
395
|
-
updateBounds(totalVirtualSize, containerSize);
|
|
396
|
-
}
|
|
397
|
-
});
|
|
398
|
-
};
|
|
399
|
-
|
|
400
|
-
// Store initialize function
|
|
401
|
-
storeFeatureFunction(component, "_scrollbarInitialize", initialize);
|
|
402
|
-
|
|
403
|
-
// Hook into viewport initialization
|
|
404
|
-
wrapInitialize(component, initialize);
|
|
405
|
-
|
|
406
|
-
// Cleanup
|
|
407
|
-
const destroy = () => {
|
|
408
|
-
if (scrollbarTrack) {
|
|
409
|
-
scrollbarTrack.remove();
|
|
410
|
-
scrollbarTrack = null;
|
|
411
|
-
}
|
|
412
|
-
scrollbarThumb = null;
|
|
413
|
-
viewportElement = null;
|
|
414
|
-
isInitialized = false;
|
|
415
|
-
|
|
416
|
-
if (hideTimeout) {
|
|
417
|
-
clearTimeout(hideTimeout);
|
|
418
|
-
hideTimeout = null;
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
document.removeEventListener("mousemove", handleMouseMove);
|
|
422
|
-
document.removeEventListener("mouseup", handleMouseUp);
|
|
423
|
-
};
|
|
424
|
-
|
|
425
|
-
storeFeatureFunction(component, "_scrollbarDestroy", destroy);
|
|
426
|
-
wrapDestroy(component, destroy);
|
|
427
|
-
|
|
428
|
-
// Return enhanced component
|
|
429
|
-
return {
|
|
430
|
-
...component,
|
|
431
|
-
scrollbar: { show, hide, updateBounds, updatePosition },
|
|
432
|
-
};
|
|
433
|
-
};
|
|
434
|
-
}
|