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,133 +0,0 @@
|
|
|
1
|
-
// src/core/viewport/types.ts
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Core type definitions for Viewport
|
|
5
|
-
* Virtual scrolling and rendering types
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import type { CollectionComponent } from "./features/collection";
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Core Range and Item Types
|
|
12
|
-
*/
|
|
13
|
-
export interface ItemRange {
|
|
14
|
-
start: number;
|
|
15
|
-
end: number;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface ViewportInfo {
|
|
19
|
-
containerSize: number;
|
|
20
|
-
totalVirtualSize: number;
|
|
21
|
-
visibleRange: ItemRange;
|
|
22
|
-
virtualScrollPosition: number;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Viewport context interface - provides context for viewport features
|
|
27
|
-
*/
|
|
28
|
-
export interface ViewportContext {
|
|
29
|
-
element: HTMLElement;
|
|
30
|
-
items: any[];
|
|
31
|
-
totalItems: number;
|
|
32
|
-
template?: (item: any, index: number) => string | HTMLElement;
|
|
33
|
-
emit?: (event: string, data?: any) => void;
|
|
34
|
-
on?: (event: string, handler: Function) => () => void;
|
|
35
|
-
once?: (event: string, handler: Function) => () => void;
|
|
36
|
-
off?: (event: string, handler: Function) => void;
|
|
37
|
-
getClass?: (name: string) => string;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Viewport configuration - Feature-oriented structure
|
|
42
|
-
*/
|
|
43
|
-
export interface ViewportConfig {
|
|
44
|
-
// Basic configuration
|
|
45
|
-
element?: HTMLElement;
|
|
46
|
-
className?: string;
|
|
47
|
-
debug?: boolean;
|
|
48
|
-
|
|
49
|
-
// Template for rendering items
|
|
50
|
-
template?: (
|
|
51
|
-
item: any,
|
|
52
|
-
index: number,
|
|
53
|
-
) => string | HTMLElement | any[] | Record<string, any>;
|
|
54
|
-
|
|
55
|
-
// Collection/data source configuration
|
|
56
|
-
collection?: {
|
|
57
|
-
adapter?: any; // Data adapter
|
|
58
|
-
transform?: (item: any) => any; // Transform items before rendering
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
// Pagination configuration
|
|
62
|
-
pagination?: {
|
|
63
|
-
strategy?: "page" | "offset" | "cursor";
|
|
64
|
-
limit?: number; // Items per page/range
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
// Virtual scrolling configuration
|
|
68
|
-
virtual?: {
|
|
69
|
-
itemSize?: number;
|
|
70
|
-
overscan?: number; // Extra items to render outside viewport
|
|
71
|
-
autoDetectItemSize?: boolean; // Auto-detect item size from first render
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
// Scrolling configuration
|
|
75
|
-
scrolling?: {
|
|
76
|
-
orientation?: "vertical" | "horizontal";
|
|
77
|
-
animation?: boolean; // Smooth scrolling
|
|
78
|
-
sensitivity?: number; // Scroll sensitivity
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
// Scrollbar configuration
|
|
82
|
-
scrollbar?: {
|
|
83
|
-
enabled?: boolean;
|
|
84
|
-
autoHide?: boolean;
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
// Performance configuration
|
|
88
|
-
performance?: {
|
|
89
|
-
maxConcurrentRequests?: number;
|
|
90
|
-
cancelLoadThreshold?: number; // Velocity threshold for cancelling loads
|
|
91
|
-
enableRequestQueue?: boolean;
|
|
92
|
-
recycleElements?: boolean;
|
|
93
|
-
bufferSize?: number;
|
|
94
|
-
renderDebounce?: number;
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
// Placeholder configuration
|
|
98
|
-
placeholders?: {
|
|
99
|
-
enabled?: boolean;
|
|
100
|
-
template?: (index: number) => string | HTMLElement;
|
|
101
|
-
maskCharacter?: string;
|
|
102
|
-
analyzeFirstLoad?: boolean;
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Enhanced component after viewport is applied
|
|
108
|
-
*/
|
|
109
|
-
export interface ViewportComponent extends ViewportContext {
|
|
110
|
-
viewport: {
|
|
111
|
-
// Core API
|
|
112
|
-
initialize(): boolean | void;
|
|
113
|
-
destroy(): void;
|
|
114
|
-
updateViewport(): void;
|
|
115
|
-
|
|
116
|
-
// Scrolling
|
|
117
|
-
scrollToIndex(index: number, alignment?: "start" | "center" | "end"): void;
|
|
118
|
-
scrollToPosition(position: number): void;
|
|
119
|
-
getScrollPosition(): number;
|
|
120
|
-
scrollBy(delta: number): void;
|
|
121
|
-
getVelocity(): number;
|
|
122
|
-
|
|
123
|
-
// Collection feature (optional)
|
|
124
|
-
collection?: CollectionComponent["collection"];
|
|
125
|
-
|
|
126
|
-
// Info
|
|
127
|
-
getVisibleRange(): ItemRange;
|
|
128
|
-
getViewportInfo(): ViewportInfo;
|
|
129
|
-
|
|
130
|
-
// Rendering
|
|
131
|
-
renderItems(): void;
|
|
132
|
-
};
|
|
133
|
-
}
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
// src/core/viewport/utils/speed-tracker.ts
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Speed tracking utility for viewport
|
|
5
|
-
* Measures velocity and determines loading strategies
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { VIEWPORT_CONSTANTS } from "../constants";
|
|
9
|
-
|
|
10
|
-
export interface SpeedTracker {
|
|
11
|
-
velocity: number;
|
|
12
|
-
direction: "forward" | "backward";
|
|
13
|
-
isAccelerating: boolean;
|
|
14
|
-
lastMeasurement: number;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Create a new speed tracker instance
|
|
19
|
-
*/
|
|
20
|
-
export function createSpeedTracker(): SpeedTracker {
|
|
21
|
-
return {
|
|
22
|
-
velocity: 0,
|
|
23
|
-
direction: "forward",
|
|
24
|
-
isAccelerating: false,
|
|
25
|
-
lastMeasurement: Date.now(),
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Update speed tracker with new scroll position
|
|
31
|
-
*/
|
|
32
|
-
export function updateSpeedTracker(
|
|
33
|
-
tracker: SpeedTracker,
|
|
34
|
-
newPosition: number,
|
|
35
|
-
previousPosition: number
|
|
36
|
-
): SpeedTracker {
|
|
37
|
-
const now = Date.now();
|
|
38
|
-
const deltaTime = now - tracker.lastMeasurement;
|
|
39
|
-
const deltaPosition = newPosition - previousPosition;
|
|
40
|
-
|
|
41
|
-
// Calculate velocity (px/ms)
|
|
42
|
-
const currentVelocity =
|
|
43
|
-
deltaTime > 0 ? Math.abs(deltaPosition) / deltaTime : 0;
|
|
44
|
-
|
|
45
|
-
// Determine direction
|
|
46
|
-
const direction = deltaPosition >= 0 ? "forward" : "backward";
|
|
47
|
-
|
|
48
|
-
// Check if accelerating
|
|
49
|
-
const isAccelerating = currentVelocity > tracker.velocity;
|
|
50
|
-
|
|
51
|
-
// Apply smoothing for more stable velocity tracking
|
|
52
|
-
const smoothingFactor = 0.85;
|
|
53
|
-
const smoothedVelocity =
|
|
54
|
-
tracker.velocity * smoothingFactor +
|
|
55
|
-
currentVelocity * (1 - smoothingFactor);
|
|
56
|
-
|
|
57
|
-
return {
|
|
58
|
-
velocity: smoothedVelocity,
|
|
59
|
-
direction,
|
|
60
|
-
isAccelerating,
|
|
61
|
-
lastMeasurement: now,
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Determine if scroll speed is fast (should defer loading)
|
|
67
|
-
*/
|
|
68
|
-
export function isFastScrolling(tracker: SpeedTracker): boolean {
|
|
69
|
-
return tracker.velocity > VIEWPORT_CONSTANTS.LOADING.CANCEL_THRESHOLD;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Get loading strategy based on current speed
|
|
74
|
-
*/
|
|
75
|
-
export function getLoadingStrategy(
|
|
76
|
-
tracker: SpeedTracker
|
|
77
|
-
): "defer" | "immediate" {
|
|
78
|
-
return isFastScrolling(tracker) ? "defer" : "immediate";
|
|
79
|
-
}
|
|
@@ -1,265 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Viewport - Core virtual scrolling engine
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import type {
|
|
6
|
-
ViewportConfig,
|
|
7
|
-
ViewportContext,
|
|
8
|
-
ViewportComponent,
|
|
9
|
-
ItemRange,
|
|
10
|
-
ViewportInfo,
|
|
11
|
-
} from "./types";
|
|
12
|
-
import { pipe } from "mtrl";
|
|
13
|
-
import { withBase } from "./features/base";
|
|
14
|
-
import { withVirtual } from "./features/virtual";
|
|
15
|
-
import { withScrolling } from "./features/scrolling";
|
|
16
|
-
import { withScrollbar } from "./features/scrollbar";
|
|
17
|
-
import { withCollection } from "./features/collection";
|
|
18
|
-
import { withPlaceholders } from "./features/placeholders";
|
|
19
|
-
import { withRendering } from "./features/rendering";
|
|
20
|
-
import { withEvents } from "./features/events";
|
|
21
|
-
|
|
22
|
-
// Internal viewport state
|
|
23
|
-
interface ViewportState {
|
|
24
|
-
scrollPosition: number;
|
|
25
|
-
totalItems: number;
|
|
26
|
-
itemSize: number;
|
|
27
|
-
containerSize: number;
|
|
28
|
-
virtualTotalSize: number;
|
|
29
|
-
visibleRange: ItemRange;
|
|
30
|
-
itemsContainer: HTMLElement | null;
|
|
31
|
-
velocity: number;
|
|
32
|
-
scrollDirection: "forward" | "backward";
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Creates a viewport-enhanced component using composition
|
|
37
|
-
*
|
|
38
|
-
* @param config - Viewport configuration
|
|
39
|
-
* @returns Function that enhances a component with viewport capabilities
|
|
40
|
-
*/
|
|
41
|
-
export const createViewport = (config: ViewportConfig = {}) => {
|
|
42
|
-
return <T extends ViewportContext>(component: T): T & ViewportComponent => {
|
|
43
|
-
// Track if viewport has been initialized to prevent multiple initializations
|
|
44
|
-
let isInitialized = false;
|
|
45
|
-
|
|
46
|
-
// No normalization needed - we'll use the nested structure directly
|
|
47
|
-
|
|
48
|
-
// Create shared viewport state
|
|
49
|
-
const state: ViewportState = {
|
|
50
|
-
scrollPosition: 0,
|
|
51
|
-
totalItems: component.totalItems || 0,
|
|
52
|
-
itemSize: config.virtual?.itemSize || 50,
|
|
53
|
-
containerSize: 0,
|
|
54
|
-
virtualTotalSize: 0,
|
|
55
|
-
visibleRange: { start: 0, end: 0 },
|
|
56
|
-
itemsContainer: null,
|
|
57
|
-
velocity: 0,
|
|
58
|
-
scrollDirection: "forward",
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
// Create base viewport API
|
|
62
|
-
const viewportAPI = {
|
|
63
|
-
// Core API
|
|
64
|
-
initialize: () => {
|
|
65
|
-
// Prevent multiple initializations
|
|
66
|
-
if (isInitialized) {
|
|
67
|
-
return false;
|
|
68
|
-
}
|
|
69
|
-
isInitialized = true;
|
|
70
|
-
|
|
71
|
-
// console.log("[Viewport] Initializing with state:", {
|
|
72
|
-
// element: !!component.element,
|
|
73
|
-
// totalItems: component.totalItems,
|
|
74
|
-
// itemSize: config.virtual?.itemSize,
|
|
75
|
-
// });
|
|
76
|
-
|
|
77
|
-
// Initialize container size
|
|
78
|
-
if (component.element) {
|
|
79
|
-
state.containerSize =
|
|
80
|
-
config.scrolling?.orientation === "horizontal"
|
|
81
|
-
? component.element.offsetWidth
|
|
82
|
-
: component.element.offsetHeight;
|
|
83
|
-
|
|
84
|
-
// console.log("[Viewport] Container size:", state.containerSize);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Calculate initial virtual size
|
|
88
|
-
state.virtualTotalSize = state.totalItems * state.itemSize;
|
|
89
|
-
|
|
90
|
-
// Calculate initial visible range
|
|
91
|
-
state.visibleRange = calculateVisibleRange(state.scrollPosition);
|
|
92
|
-
|
|
93
|
-
// console.log("[Viewport] Initial state:", {
|
|
94
|
-
// containerSize: state.containerSize,
|
|
95
|
-
// virtualTotalSize: state.virtualTotalSize,
|
|
96
|
-
// visibleRange: state.visibleRange,
|
|
97
|
-
// });
|
|
98
|
-
},
|
|
99
|
-
|
|
100
|
-
destroy: () => {
|
|
101
|
-
// Cleanup will be handled by features
|
|
102
|
-
},
|
|
103
|
-
|
|
104
|
-
updateViewport: () => {
|
|
105
|
-
// Will be implemented by rendering feature
|
|
106
|
-
},
|
|
107
|
-
|
|
108
|
-
// Check if already initialized
|
|
109
|
-
isInitialized: () => isInitialized,
|
|
110
|
-
|
|
111
|
-
// Allow features to check if init should proceed
|
|
112
|
-
_shouldInit: () => !isInitialized,
|
|
113
|
-
|
|
114
|
-
// Scrolling API (will be overridden by scrolling feature)
|
|
115
|
-
scrollToIndex: (
|
|
116
|
-
index: number,
|
|
117
|
-
alignment?: "start" | "center" | "end",
|
|
118
|
-
) => {
|
|
119
|
-
// Placeholder - will be implemented by scrolling feature
|
|
120
|
-
},
|
|
121
|
-
|
|
122
|
-
scrollToPosition: (position: number) => {
|
|
123
|
-
// Will be implemented by scrolling feature
|
|
124
|
-
},
|
|
125
|
-
|
|
126
|
-
getScrollPosition: () => state.scrollPosition,
|
|
127
|
-
|
|
128
|
-
// Info API
|
|
129
|
-
getVisibleRange: () => state.visibleRange,
|
|
130
|
-
|
|
131
|
-
getViewportInfo: (): ViewportInfo => ({
|
|
132
|
-
containerSize: state.containerSize,
|
|
133
|
-
totalVirtualSize: state.virtualTotalSize,
|
|
134
|
-
visibleRange: state.visibleRange,
|
|
135
|
-
virtualScrollPosition: state.scrollPosition,
|
|
136
|
-
}),
|
|
137
|
-
|
|
138
|
-
// Rendering API
|
|
139
|
-
renderItems: () => {
|
|
140
|
-
// Will be implemented by rendering feature
|
|
141
|
-
},
|
|
142
|
-
|
|
143
|
-
// Internal state (for features to access)
|
|
144
|
-
state,
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
// Helper function to calculate visible range
|
|
148
|
-
const calculateVisibleRange = (scrollPos: number): ItemRange => {
|
|
149
|
-
const itemSize = state.itemSize;
|
|
150
|
-
const start = Math.floor(scrollPos / itemSize);
|
|
151
|
-
const visibleCount = Math.ceil(state.containerSize / itemSize);
|
|
152
|
-
const end = Math.min(start + visibleCount, state.totalItems - 1);
|
|
153
|
-
|
|
154
|
-
return { start: Math.max(0, start), end: Math.max(0, end) };
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
// Add viewport API to component
|
|
158
|
-
const baseComponent = {
|
|
159
|
-
...component,
|
|
160
|
-
viewport: viewportAPI,
|
|
161
|
-
};
|
|
162
|
-
|
|
163
|
-
// Build the enhancement pipeline
|
|
164
|
-
const enhancers: Array<(c: any) => any> = [];
|
|
165
|
-
|
|
166
|
-
// Events system (always first - provides communication for other features)
|
|
167
|
-
enhancers.push(
|
|
168
|
-
withEvents({
|
|
169
|
-
debug: config.debug,
|
|
170
|
-
}),
|
|
171
|
-
);
|
|
172
|
-
|
|
173
|
-
// Base setup (creates DOM structure)
|
|
174
|
-
enhancers.push(
|
|
175
|
-
withBase({
|
|
176
|
-
className: config.className,
|
|
177
|
-
orientation: config.scrolling?.orientation,
|
|
178
|
-
}),
|
|
179
|
-
);
|
|
180
|
-
|
|
181
|
-
// Virtual scrolling (required for most features)
|
|
182
|
-
enhancers.push(
|
|
183
|
-
withVirtual({
|
|
184
|
-
itemSize: config.virtual?.itemSize,
|
|
185
|
-
overscan: config.virtual?.overscan,
|
|
186
|
-
orientation: config.scrolling?.orientation,
|
|
187
|
-
autoDetectItemSize: config.virtual?.autoDetectItemSize,
|
|
188
|
-
initialScrollIndex: (config as any).initialScrollIndex,
|
|
189
|
-
}),
|
|
190
|
-
);
|
|
191
|
-
|
|
192
|
-
// Scrolling behavior
|
|
193
|
-
enhancers.push(
|
|
194
|
-
withScrolling({
|
|
195
|
-
orientation: config.scrolling?.orientation,
|
|
196
|
-
sensitivity: config.scrolling?.sensitivity,
|
|
197
|
-
smoothing: config.scrolling?.animation,
|
|
198
|
-
}),
|
|
199
|
-
);
|
|
200
|
-
|
|
201
|
-
// Scrollbar (optional)
|
|
202
|
-
if (config.scrollbar?.enabled !== false) {
|
|
203
|
-
enhancers.push(
|
|
204
|
-
withScrollbar({
|
|
205
|
-
enabled: true,
|
|
206
|
-
autoHide: config.scrollbar?.autoHide,
|
|
207
|
-
}),
|
|
208
|
-
);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
// Add collection if configured
|
|
212
|
-
if (config.collection?.adapter) {
|
|
213
|
-
enhancers.push(
|
|
214
|
-
withCollection({
|
|
215
|
-
collection: config.collection.adapter,
|
|
216
|
-
rangeSize: config.pagination?.limit,
|
|
217
|
-
strategy: config.pagination?.strategy as
|
|
218
|
-
| "offset"
|
|
219
|
-
| "page"
|
|
220
|
-
| "cursor"
|
|
221
|
-
| undefined,
|
|
222
|
-
transform: config.collection?.transform,
|
|
223
|
-
cancelLoadThreshold: config.performance?.cancelLoadThreshold,
|
|
224
|
-
maxConcurrentRequests: config.performance?.maxConcurrentRequests,
|
|
225
|
-
enableRequestQueue: config.performance?.enableRequestQueue !== false,
|
|
226
|
-
initialScrollIndex: (config as any).initialScrollIndex,
|
|
227
|
-
selectId: (config as any).selectId,
|
|
228
|
-
autoLoad: (config as any).autoLoad !== false,
|
|
229
|
-
}),
|
|
230
|
-
);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// Placeholders (optional, requires collection)
|
|
234
|
-
if (config.collection?.adapter && config.placeholders?.enabled !== false) {
|
|
235
|
-
enhancers.push(
|
|
236
|
-
withPlaceholders({
|
|
237
|
-
enabled: true,
|
|
238
|
-
analyzeFirstLoad: config.placeholders?.analyzeFirstLoad ?? true,
|
|
239
|
-
maskCharacter: config.placeholders?.maskCharacter,
|
|
240
|
-
}),
|
|
241
|
-
);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
// Rendering (always last to have access to all features)
|
|
245
|
-
enhancers.push(
|
|
246
|
-
withRendering({
|
|
247
|
-
template: config.template,
|
|
248
|
-
overscan: config.virtual?.overscan,
|
|
249
|
-
}),
|
|
250
|
-
);
|
|
251
|
-
|
|
252
|
-
// Compose all enhancers
|
|
253
|
-
const enhance = pipe(...enhancers);
|
|
254
|
-
|
|
255
|
-
// Apply enhancements
|
|
256
|
-
const enhanced = enhance(baseComponent);
|
|
257
|
-
|
|
258
|
-
// Auto-initialize if element is provided
|
|
259
|
-
if (enhanced.element) {
|
|
260
|
-
enhanced.viewport.initialize();
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
return enhanced as T & ViewportComponent;
|
|
264
|
-
};
|
|
265
|
-
};
|