mtrl-addons 0.1.2 → 0.2.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.
Files changed (117) hide show
  1. package/AI.md +28 -230
  2. package/CLAUDE.md +882 -0
  3. package/build.js +253 -24
  4. package/package.json +14 -4
  5. package/scripts/debug/vlist-selection.ts +121 -0
  6. package/src/components/index.ts +5 -41
  7. package/src/components/{list → vlist}/config.ts +66 -95
  8. package/src/components/vlist/constants.ts +23 -0
  9. package/src/components/vlist/features/api.ts +626 -0
  10. package/src/components/vlist/features/index.ts +10 -0
  11. package/src/components/vlist/features/selection.ts +436 -0
  12. package/src/components/vlist/features/viewport.ts +59 -0
  13. package/src/components/vlist/index.ts +17 -0
  14. package/src/components/{list → vlist}/types.ts +242 -32
  15. package/src/components/vlist/vlist.ts +92 -0
  16. package/src/core/compose/features/gestures/index.ts +227 -0
  17. package/src/core/compose/features/gestures/longpress.ts +383 -0
  18. package/src/core/compose/features/gestures/pan.ts +424 -0
  19. package/src/core/compose/features/gestures/pinch.ts +475 -0
  20. package/src/core/compose/features/gestures/rotate.ts +485 -0
  21. package/src/core/compose/features/gestures/swipe.ts +492 -0
  22. package/src/core/compose/features/gestures/tap.ts +334 -0
  23. package/src/core/compose/features/index.ts +2 -38
  24. package/src/core/compose/index.ts +13 -29
  25. package/src/core/gestures/index.ts +31 -0
  26. package/src/core/gestures/longpress.ts +68 -0
  27. package/src/core/gestures/manager.ts +418 -0
  28. package/src/core/gestures/pan.ts +48 -0
  29. package/src/core/gestures/pinch.ts +58 -0
  30. package/src/core/gestures/rotate.ts +58 -0
  31. package/src/core/gestures/swipe.ts +66 -0
  32. package/src/core/gestures/tap.ts +45 -0
  33. package/src/core/gestures/types.ts +387 -0
  34. package/src/core/gestures/utils.ts +128 -0
  35. package/src/core/index.ts +27 -151
  36. package/src/core/layout/schema.ts +153 -72
  37. package/src/core/layout/types.ts +5 -2
  38. package/src/core/viewport/constants.ts +145 -0
  39. package/src/core/viewport/features/base.ts +73 -0
  40. package/src/core/viewport/features/collection.ts +1182 -0
  41. package/src/core/viewport/features/events.ts +130 -0
  42. package/src/core/viewport/features/index.ts +20 -0
  43. package/src/core/{list-manager/features/viewport → viewport/features}/item-size.ts +31 -34
  44. package/src/core/{list-manager/features/viewport → viewport/features}/loading.ts +4 -4
  45. package/src/core/viewport/features/momentum.ts +269 -0
  46. package/src/core/viewport/features/placeholders.ts +335 -0
  47. package/src/core/viewport/features/rendering.ts +962 -0
  48. package/src/core/viewport/features/scrollbar.ts +434 -0
  49. package/src/core/viewport/features/scrolling.ts +634 -0
  50. package/src/core/viewport/features/utils.ts +94 -0
  51. package/src/core/viewport/features/virtual.ts +525 -0
  52. package/src/core/viewport/index.ts +31 -0
  53. package/src/core/viewport/types.ts +133 -0
  54. package/src/core/viewport/utils/speed-tracker.ts +79 -0
  55. package/src/core/viewport/viewport.ts +265 -0
  56. package/src/index.ts +0 -7
  57. package/src/styles/components/_vlist.scss +352 -0
  58. package/src/styles/index.scss +1 -1
  59. package/test/components/vlist-selection.test.ts +240 -0
  60. package/test/components/vlist.test.ts +63 -0
  61. package/test/core/collection/adapter.test.ts +161 -0
  62. package/bun.lock +0 -792
  63. package/src/components/list/api.ts +0 -314
  64. package/src/components/list/constants.ts +0 -56
  65. package/src/components/list/features/api.ts +0 -428
  66. package/src/components/list/features/index.ts +0 -31
  67. package/src/components/list/features/list-manager.ts +0 -502
  68. package/src/components/list/index.ts +0 -39
  69. package/src/components/list/list.ts +0 -234
  70. package/src/core/collection/base-collection.ts +0 -100
  71. package/src/core/collection/collection-composer.ts +0 -178
  72. package/src/core/collection/collection.ts +0 -745
  73. package/src/core/collection/constants.ts +0 -172
  74. package/src/core/collection/events.ts +0 -428
  75. package/src/core/collection/features/api/loading.ts +0 -279
  76. package/src/core/collection/features/operations/data-operations.ts +0 -147
  77. package/src/core/collection/index.ts +0 -104
  78. package/src/core/collection/state.ts +0 -497
  79. package/src/core/collection/types.ts +0 -404
  80. package/src/core/compose/features/collection.ts +0 -119
  81. package/src/core/compose/features/selection.ts +0 -213
  82. package/src/core/compose/features/styling.ts +0 -108
  83. package/src/core/list-manager/api.ts +0 -599
  84. package/src/core/list-manager/config.ts +0 -593
  85. package/src/core/list-manager/constants.ts +0 -268
  86. package/src/core/list-manager/features/api.ts +0 -58
  87. package/src/core/list-manager/features/collection/collection.ts +0 -705
  88. package/src/core/list-manager/features/collection/index.ts +0 -17
  89. package/src/core/list-manager/features/viewport/constants.ts +0 -42
  90. package/src/core/list-manager/features/viewport/index.ts +0 -16
  91. package/src/core/list-manager/features/viewport/placeholders.ts +0 -281
  92. package/src/core/list-manager/features/viewport/rendering.ts +0 -575
  93. package/src/core/list-manager/features/viewport/scrollbar.ts +0 -495
  94. package/src/core/list-manager/features/viewport/scrolling.ts +0 -795
  95. package/src/core/list-manager/features/viewport/template.ts +0 -220
  96. package/src/core/list-manager/features/viewport/viewport.ts +0 -654
  97. package/src/core/list-manager/features/viewport/virtual.ts +0 -309
  98. package/src/core/list-manager/index.ts +0 -279
  99. package/src/core/list-manager/list-manager.ts +0 -206
  100. package/src/core/list-manager/types.ts +0 -439
  101. package/src/core/list-manager/utils/calculations.ts +0 -290
  102. package/src/core/list-manager/utils/range-calculator.ts +0 -349
  103. package/src/core/list-manager/utils/speed-tracker.ts +0 -273
  104. package/src/styles/components/_list.scss +0 -244
  105. package/src/types/mtrl.d.ts +0 -6
  106. package/test/components/list.test.ts +0 -256
  107. package/test/core/collection/failed-ranges.test.ts +0 -270
  108. package/test/core/compose/features.test.ts +0 -183
  109. package/test/core/list-manager/features/collection.test.ts +0 -704
  110. package/test/core/list-manager/features/viewport.test.ts +0 -698
  111. package/test/core/list-manager/list-manager.test.ts +0 -593
  112. package/test/core/list-manager/utils/calculations.test.ts +0 -433
  113. package/test/core/list-manager/utils/range-calculator.test.ts +0 -569
  114. package/test/core/list-manager/utils/speed-tracker.test.ts +0 -530
  115. package/tsconfig.build.json +0 -23
  116. /package/src/components/{list → vlist}/features.ts +0 -0
  117. /package/src/core/{compose → viewport}/features/performance.ts +0 -0
@@ -1,206 +0,0 @@
1
- /**
2
- * List Manager - High-Performance Virtual List Management
3
- * A clean, composable factory for creating optimized virtual lists
4
- */
5
-
6
- import { pipe } from "../compose";
7
- import { withCollection } from "./features/collection/collection";
8
- import { withViewport } from "./features/viewport/viewport";
9
- import { withPlaceholders } from "./features/viewport/placeholders";
10
- import { createLoadingManager } from "./features/viewport/loading";
11
- import { LIST_MANAGER_CONSTANTS } from "./constants";
12
- import type { ListManagerConfig, ListManagerComponent } from "./types";
13
-
14
- /**
15
- * Default configuration for List Manager
16
- */
17
- const DEFAULT_CONFIG: Partial<ListManagerConfig> = {
18
- orientation: {
19
- orientation: "vertical",
20
- reverse: false,
21
- crossAxisAlignment: "stretch",
22
- },
23
- virtual: {
24
- estimatedItemSize: LIST_MANAGER_CONSTANTS.VIRTUAL_SCROLL.DEFAULT_ITEM_SIZE,
25
- itemSize: LIST_MANAGER_CONSTANTS.VIRTUAL_SCROLL.DEFAULT_ITEM_SIZE,
26
- overscan: LIST_MANAGER_CONSTANTS.VIRTUAL_SCROLL.OVERSCAN_BUFFER,
27
- enabled: true,
28
- },
29
- collection: {
30
- pageSize: LIST_MANAGER_CONSTANTS.RANGE_LOADING.DEFAULT_RANGE_SIZE,
31
- strategy: "page",
32
- },
33
- };
34
-
35
- /**
36
- * Creates a new List Manager component
37
- */
38
- export const createListManager = (
39
- config: ListManagerConfig
40
- ): ListManagerComponent => {
41
- const container = config.container;
42
-
43
- // Merge config with defaults - handle undefined properties
44
- const mergedConfig: ListManagerConfig = {
45
- ...DEFAULT_CONFIG,
46
- ...config,
47
- orientation: {
48
- ...DEFAULT_CONFIG.orientation,
49
- ...(config.orientation || {}),
50
- },
51
- virtual: {
52
- ...DEFAULT_CONFIG.virtual,
53
- ...(config.virtual || {}),
54
- },
55
- collection: {
56
- ...DEFAULT_CONFIG.collection,
57
- ...(config.collection || {}),
58
- },
59
- } as ListManagerConfig;
60
-
61
- // Create base component
62
- const createBaseComponent = (): ListManagerComponent => {
63
- // Simple event system
64
- const eventListeners = new Map<string, Function[]>();
65
-
66
- const emit = (event: string, data?: any) => {
67
- const listeners = eventListeners.get(event) || [];
68
- listeners.forEach((listener) => {
69
- try {
70
- listener(data);
71
- } catch (error) {
72
- console.error(`Error in event listener for ${event}:`, error);
73
- }
74
- });
75
- };
76
-
77
- const on = (event: string, listener: Function) => {
78
- if (!eventListeners.has(event)) {
79
- eventListeners.set(event, []);
80
- }
81
- eventListeners.get(event)!.push(listener);
82
-
83
- // Return unsubscribe function
84
- return () => {
85
- const listeners = eventListeners.get(event);
86
- if (listeners) {
87
- const index = listeners.indexOf(listener);
88
- if (index > -1) {
89
- listeners.splice(index, 1);
90
- }
91
- }
92
- };
93
- };
94
-
95
- return {
96
- element: container,
97
- config: mergedConfig,
98
- componentName: "list-manager",
99
- getClass: (name: string) => `mtrl-list-manager__${name}`,
100
- items: config.items || [],
101
- totalItems: config.collection?.totalItems || config.items?.length || 0,
102
- template: config.template?.template || null,
103
- isInitialized: false,
104
- isDestroyed: false,
105
- emit,
106
- on,
107
- initialize: () => {
108
- // console.log("🚀 [LIST-MANAGER] Initializing...");
109
- },
110
- destroy: () => {
111
- // console.log("👋 [LIST-MANAGER] Destroying...");
112
- },
113
- updateConfig: (update: Partial<ListManagerConfig>) => {
114
- Object.assign(mergedConfig, update);
115
- },
116
- getConfig: () => mergedConfig,
117
- };
118
- };
119
-
120
- // Create loading manager
121
- let loadingManager: ReturnType<typeof createLoadingManager> | null = null;
122
-
123
- // Compose enhancers - CRITICAL: Collection must be applied before viewport
124
- // so that viewport can access collection.loadMissingRanges
125
- const enhance = pipe(
126
- withCollection({
127
- collection: config.collection?.adapter,
128
- rangeSize: config.collection?.pageSize || 20,
129
- strategy: config.collection?.strategy || "page",
130
- enablePlaceholders: true,
131
- }),
132
- withPlaceholders({
133
- enabled: true,
134
- }),
135
- withViewport({
136
- orientation: mergedConfig.orientation?.orientation,
137
- estimatedItemSize: mergedConfig.virtual?.estimatedItemSize,
138
- overscan: mergedConfig.virtual?.overscan,
139
- enableScrollbar: true,
140
- measureItems: mergedConfig.virtual?.measureItems, // Pass measureItems flag
141
- // Pass callback to load data for a specific range
142
- loadDataForRange: (
143
- range: { start: number; end: number },
144
- priority?: "high" | "normal" | "low"
145
- ) => {
146
- // Use loading manager if available
147
- if (loadingManager) {
148
- // Check if this range is already being loaded
149
- if (!loadingManager.isRangeLoading(range)) {
150
- loadingManager.requestLoad(range, priority || "normal");
151
- }
152
- } else {
153
- // Fallback to direct collection loading
154
- setTimeout(() => {
155
- const collectionComponent = component as any;
156
- if (
157
- collectionComponent.collection &&
158
- typeof collectionComponent.collection.loadMissingRanges ===
159
- "function"
160
- ) {
161
- collectionComponent.collection
162
- .loadMissingRanges(range)
163
- .catch((error: any) => {
164
- console.error("Failed to load range:", error);
165
- });
166
- }
167
- }, 0);
168
- }
169
- },
170
- })
171
- );
172
-
173
- // Create and enhance component
174
- const component = enhance(createBaseComponent());
175
-
176
- // Create loading manager after component is enhanced
177
- loadingManager = createLoadingManager(component, {
178
- maxConcurrentRequests: config.collection?.maxConcurrentRequests,
179
- });
180
-
181
- // Wire up velocity updates from scrolling to loading manager
182
- if (component.on) {
183
- component.on("speed:changed", (data: any) => {
184
- if (loadingManager) {
185
- loadingManager.updateVelocity(data.speed, data.direction);
186
- }
187
- });
188
- }
189
-
190
- // Initialize component
191
- if ((component as any).viewport?.initialize) {
192
- (component as any).viewport.initialize();
193
- }
194
-
195
- // Return the enhanced component
196
- return component;
197
- };
198
-
199
- /**
200
- * Configuration for list manager enhancers
201
- */
202
- export interface ListManagerEnhancerConfig {
203
- viewport?: Parameters<typeof withViewport>[0];
204
- collection?: Parameters<typeof withCollection>[0];
205
- placeholders?: Parameters<typeof withPlaceholders>[0];
206
- }
@@ -1,439 +0,0 @@
1
- /**
2
- * Core type definitions for List Manager
3
- * Performance and UI management layer types
4
- */
5
-
6
- import type { ListManagerConstants } from "./constants";
7
-
8
- /**
9
- * Core Range and Item Types
10
- */
11
- export interface ItemRange {
12
- start: number;
13
- end: number;
14
- }
15
-
16
- export interface ViewportInfo {
17
- containerSize: number;
18
- totalVirtualSize: number;
19
- visibleRange: ItemRange;
20
- virtualScrollPosition: number;
21
- }
22
-
23
- export interface SpeedTracker {
24
- velocity: number; // px/ms
25
- direction: "forward" | "backward"; // scroll direction (vertical: down/up, horizontal: right/left)
26
- isAccelerating: boolean; // velocity increasing
27
- lastMeasurement: number; // timestamp of last measurement
28
- }
29
-
30
- /**
31
- * Feature Interfaces for Simplified Architecture
32
- */
33
-
34
- /**
35
- * Viewport Feature - Complete Virtual Scrolling
36
- */
37
- export interface ViewportFeature {
38
- // Orientation handling
39
- orientation: "vertical" | "horizontal";
40
-
41
- // Virtual scrolling (orientation-agnostic)
42
- virtualScrollPosition: number;
43
- totalVirtualSize: number;
44
- containerSize: number;
45
-
46
- // Item sizing (orientation-agnostic)
47
- estimatedItemSize: number;
48
- measuredSizes: Map<number, number>;
49
-
50
- // Custom scrollbar
51
- scrollbarThumb: HTMLElement | null;
52
- scrollbarTrack: HTMLElement | null;
53
- thumbPosition: number;
54
-
55
- // Methods
56
- handleWheel(event: WheelEvent): void;
57
- updateContainerPosition(): void;
58
- updateScrollbar(): void;
59
- calculateVisibleRange(): ItemRange;
60
- measureItemSize(element: HTMLElement, index: number): void;
61
- initialize(): void;
62
- destroy(): void;
63
- }
64
-
65
- /**
66
- * Collection Feature - Data Management Integration
67
- */
68
- export interface CollectionFeature {
69
- // Speed tracking
70
- speedTracker: SpeedTracker;
71
-
72
- // Range management
73
- loadedRanges: Set<number>;
74
- pendingRanges: Set<number>;
75
-
76
- // Collection integration
77
- collection: any;
78
-
79
- // Pagination strategy
80
- paginationStrategy: "page" | "offset" | "cursor";
81
-
82
- // Placeholder system
83
- placeholderStructure: Map<string, { min: number; max: number }> | null;
84
- placeholderTemplate:
85
- | ((item: any, index: number) => string | HTMLElement)
86
- | null;
87
-
88
- // Methods
89
- loadMissingRanges(visibleRange: ItemRange): void;
90
- showPlaceholders(range: ItemRange): void;
91
- updateLoadedData(items: any[], offset: number): void;
92
- adaptPaginationStrategy(strategy: "page" | "offset" | "cursor"): void;
93
- analyzeDataStructure(items: any[]): void;
94
- generatePlaceholderItem(index: number): any;
95
- initialize(): void;
96
- destroy(): void;
97
- }
98
-
99
- /**
100
- * Configuration Types
101
- */
102
- export interface CollectionConfig {
103
- adapter?: any;
104
- pageSize?: number; // becomes rangeSize
105
- strategy?: "page" | "offset" | "cursor";
106
- [key: string]: any;
107
- }
108
-
109
- export interface TemplateConfig {
110
- template: (item: any, index: number) => string | HTMLElement;
111
- }
112
-
113
- export interface VirtualConfig {
114
- enabled: boolean;
115
- itemSize: number | "auto";
116
- estimatedItemSize: number;
117
- overscan: number;
118
- measureItems?: boolean; // Optional flag to enable/disable item measurement (default: false)
119
- }
120
-
121
- export interface OrientationConfig {
122
- orientation: "vertical" | "horizontal";
123
- reverse: boolean;
124
- crossAxisAlignment: "start" | "center" | "end" | "stretch";
125
- }
126
-
127
- export interface InitialLoadConfig {
128
- strategy: "placeholders" | "direct";
129
- viewportMultiplier: number;
130
- minItems: number;
131
- maxItems: number;
132
- }
133
-
134
- export interface ErrorHandlingConfig {
135
- timeout: number;
136
- showErrorItems: boolean;
137
- retryAttempts: number;
138
- preserveScrollOnError: boolean;
139
- }
140
-
141
- export interface PositioningConfig {
142
- precisePositioning: boolean;
143
- allowPartialItems: boolean;
144
- snapToItems: boolean;
145
- }
146
-
147
- export interface BoundariesConfig {
148
- preventOverscroll: boolean;
149
- maintainEdgeRanges: boolean;
150
- boundaryResistance: number;
151
- }
152
-
153
- export interface RecyclingConfig {
154
- enabled: boolean;
155
- maxPoolSize: number;
156
- minPoolSize: number;
157
- }
158
-
159
- export interface PerformanceConfig {
160
- frameScheduling: boolean;
161
- memoryCleanup: boolean;
162
- }
163
-
164
- export interface IntersectionConfig {
165
- pagination: {
166
- enabled: boolean;
167
- rootMargin: string;
168
- threshold: number;
169
- };
170
- loading: {
171
- enabled: boolean;
172
- };
173
- }
174
-
175
- /**
176
- * Main List Manager Configuration
177
- */
178
- export interface ListManagerConfig {
179
- // Container
180
- container: HTMLElement;
181
-
182
- // Collection integration
183
- collection?: CollectionConfig;
184
- items?: any[];
185
-
186
- // Template
187
- template?: TemplateConfig;
188
-
189
- // Virtual scrolling
190
- virtual: VirtualConfig;
191
-
192
- // Orientation
193
- orientation: OrientationConfig;
194
-
195
- // Initial loading
196
- initialLoad: InitialLoadConfig;
197
-
198
- // Error handling
199
- errorHandling: ErrorHandlingConfig;
200
-
201
- // Positioning
202
- positioning: PositioningConfig;
203
-
204
- // Boundaries
205
- boundaries: BoundariesConfig;
206
-
207
- // Element recycling (Phase 2)
208
- recycling: RecyclingConfig;
209
-
210
- // Performance
211
- performance: PerformanceConfig;
212
-
213
- // Intersection observers
214
- intersection: IntersectionConfig;
215
-
216
- // Debug
217
- debug: boolean;
218
- prefix: string;
219
- componentName: string;
220
-
221
- // Constants override
222
- constants?: Partial<ListManagerConstants>;
223
- }
224
-
225
- /**
226
- * Event System
227
- */
228
- export enum ListManagerEvents {
229
- // Virtual scrolling
230
- VIEWPORT_CHANGED = "viewport:changed",
231
- SCROLL_POSITION_CHANGED = "scroll:position:changed",
232
- VIRTUAL_RANGE_CHANGED = "virtual:range:changed",
233
- RANGE_RENDERED = "range:rendered",
234
-
235
- // Collection coordination
236
- LOADING_TRIGGERED = "loading:triggered",
237
- SPEED_CHANGED = "speed:changed",
238
- RANGE_LOADED = "range:loaded",
239
-
240
- // Orientation
241
- ORIENTATION_CHANGED = "orientation:changed",
242
- DIMENSIONS_CHANGED = "orientation:dimensions:changed",
243
-
244
- // Placeholder system
245
- STRUCTURE_ANALYZED = "placeholder:structure:analyzed",
246
- PLACEHOLDERS_SHOWN = "placeholder:shown",
247
- PLACEHOLDERS_REPLACED = "placeholder:replaced",
248
-
249
- // Element recycling events
250
- ELEMENT_RENDERED = "element:rendered",
251
- ELEMENT_UPDATED = "element:updated",
252
- ELEMENT_RECYCLED = "element:recycled",
253
- RECYCLING_INITIALIZED = "recycling:initialized",
254
- RECYCLING_DESTROYED = "recycling:destroyed",
255
-
256
- // Error handling
257
- ERROR_OCCURRED = "error:occurred",
258
- ERROR_RECOVERED = "error:recovered",
259
-
260
- // Lifecycle
261
- INITIALIZED = "lifecycle:initialized",
262
- DESTROYED = "lifecycle:destroyed",
263
- }
264
-
265
- export interface ListManagerEventData {
266
- [ListManagerEvents.VIEWPORT_CHANGED]: ViewportInfo;
267
- [ListManagerEvents.SCROLL_POSITION_CHANGED]: {
268
- position: number;
269
- direction: "forward" | "backward";
270
- };
271
- [ListManagerEvents.VIRTUAL_RANGE_CHANGED]: ItemRange;
272
- [ListManagerEvents.RANGE_RENDERED]: { range: ItemRange };
273
- [ListManagerEvents.LOADING_TRIGGERED]: { range: ItemRange; strategy: string };
274
- [ListManagerEvents.SPEED_CHANGED]: {
275
- speed: number;
276
- direction: "forward" | "backward";
277
- };
278
- [ListManagerEvents.RANGE_LOADED]: { range: ItemRange; items: any[] };
279
- [ListManagerEvents.ORIENTATION_CHANGED]: {
280
- orientation: "vertical" | "horizontal";
281
- };
282
- [ListManagerEvents.DIMENSIONS_CHANGED]: {
283
- containerSize: number;
284
- totalVirtualSize: number;
285
- };
286
- [ListManagerEvents.STRUCTURE_ANALYZED]: {
287
- structure: Map<string, { min: number; max: number }>;
288
- };
289
- [ListManagerEvents.PLACEHOLDERS_SHOWN]: { range: ItemRange; count: number };
290
- [ListManagerEvents.PLACEHOLDERS_REPLACED]: { range: ItemRange; items: any[] };
291
- [ListManagerEvents.ELEMENT_RENDERED]: { element: HTMLElement };
292
- [ListManagerEvents.ELEMENT_UPDATED]: { element: HTMLElement };
293
- [ListManagerEvents.ELEMENT_RECYCLED]: { element: HTMLElement };
294
- [ListManagerEvents.RECYCLING_INITIALIZED]: { config: ListManagerConfig };
295
- [ListManagerEvents.RECYCLING_DESTROYED]: { reason?: string };
296
- [ListManagerEvents.ERROR_OCCURRED]: { error: Error; context: string };
297
- [ListManagerEvents.ERROR_RECOVERED]: {
298
- previousError: Error;
299
- context: string;
300
- };
301
- [ListManagerEvents.INITIALIZED]: { config: ListManagerConfig };
302
- [ListManagerEvents.DESTROYED]: { reason?: string };
303
- }
304
-
305
- export interface ListManagerObserver {
306
- <T extends ListManagerEvents>(event: T, data: ListManagerEventData[T]): void;
307
- }
308
-
309
- export type ListManagerUnsubscribe = () => void;
310
-
311
- /**
312
- * Main List Manager Interface
313
- */
314
- export interface ListManager {
315
- // Virtual scrolling (orientation-agnostic)
316
- scrollToIndex(index: number, alignment?: "start" | "center" | "end"): void;
317
- scrollToPage(page: number, alignment?: "start" | "center" | "end"): void;
318
- getScrollPosition(): number;
319
-
320
- // Viewport management
321
- getVisibleRange(): ItemRange;
322
- getViewportInfo(): ViewportInfo;
323
- updateViewport(): void;
324
-
325
- // Collection integration
326
- setItems(items: any[]): void;
327
- setTotalItems(total: number): void;
328
- getItems(): any[];
329
- getTotalItems(): number;
330
-
331
- // Pagination strategy
332
- setPaginationStrategy(strategy: "page" | "offset" | "cursor"): void;
333
- getPaginationStrategy(): "page" | "offset" | "cursor";
334
-
335
- // Configuration
336
- updateConfig(config: Partial<ListManagerConfig>): void;
337
- getConfig(): ListManagerConfig;
338
-
339
- // Events
340
- subscribe(observer: ListManagerObserver): ListManagerUnsubscribe;
341
- emit<T extends ListManagerEvents>(
342
- event: T,
343
- data: ListManagerEventData[T]
344
- ): void;
345
-
346
- // Lifecycle
347
- initialize(): void;
348
- destroy(): void;
349
- }
350
-
351
- /**
352
- * Utility Types
353
- */
354
- export type ListManagerConfigUpdate = Partial<ListManagerConfig>;
355
-
356
- export interface FeatureContext {
357
- config: ListManagerConfig;
358
- constants: ListManagerConstants;
359
- emit: <T extends ListManagerEvents>(
360
- event: T,
361
- data: ListManagerEventData[T]
362
- ) => void;
363
- }
364
-
365
- export interface RangeCalculationResult {
366
- visibleRange: ItemRange;
367
- loadedRanges: Set<number>;
368
- missingRanges: ItemRange[];
369
- bufferRanges: ItemRange[];
370
- }
371
-
372
- /**
373
- * Type for the base List Manager component
374
- */
375
- export interface ListManagerComponent {
376
- // mtrl base properties
377
- element: HTMLElement;
378
- config: ListManagerConfig;
379
- componentName: string;
380
- getClass: (name: string) => string;
381
- emit?: (event: string, data?: any) => void;
382
- on?: (event: string, handler: Function) => () => void;
383
-
384
- // List Manager specific
385
- items: any[];
386
- totalItems: number;
387
- template: ((item: any, index: number) => string | HTMLElement) | null;
388
- isInitialized: boolean;
389
- isDestroyed: boolean;
390
-
391
- // Core methods
392
- initialize(): void;
393
- destroy(): void;
394
- updateConfig(config: Partial<ListManagerConfig>): void;
395
- getConfig(): ListManagerConfig;
396
- }
397
-
398
- export interface TemplateFunction {
399
- (item: any, index: number): string | HTMLElement;
400
- }
401
-
402
- export interface CollectionComponent extends ListManagerComponent {
403
- collection: {
404
- // Data management
405
- setItems: (items: any[]) => void;
406
- getItems: () => any[];
407
- setTotalItems: (total: number) => void;
408
- getTotalItems: () => number;
409
-
410
- // Range management
411
- loadRange: (offset: number, limit: number) => Promise<any[]>;
412
- loadMissingRanges: (visibleRange: ItemRange) => Promise<void>;
413
- getLoadedRanges: () => Set<number>;
414
- getPendingRanges: () => Set<number>;
415
- getFailedRanges: () => Map<
416
- number,
417
- { attempts: number; lastError: Error; timestamp: number }
418
- >;
419
- clearFailedRanges: () => void;
420
- retryFailedRange: (rangeId: number) => Promise<any[]>;
421
-
422
- // Pagination strategy
423
- setPaginationStrategy: (strategy: "page" | "offset" | "cursor") => void;
424
- getPaginationStrategy: () => string;
425
-
426
- // Placeholder system
427
- analyzeDataStructure: (items: any[]) => void;
428
- generatePlaceholderItem: (index: number) => any;
429
- showPlaceholders: (count: number) => void;
430
- getPlaceholderStructure: () => Map<
431
- string,
432
- { min: number; max: number }
433
- > | null;
434
-
435
- // State
436
- isInitialized: () => boolean;
437
- updateLoadedData: (items: any[], offset: number) => void;
438
- };
439
- }