mtrl-addons 0.1.1 → 0.2.1

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 (115) hide show
  1. package/build.js +139 -108
  2. package/package.json +13 -4
  3. package/scripts/debug/vlist-selection.ts +121 -0
  4. package/src/components/index.ts +5 -41
  5. package/src/components/{list → vlist}/config.ts +66 -95
  6. package/src/components/vlist/constants.ts +23 -0
  7. package/src/components/vlist/features/api.ts +322 -0
  8. package/src/components/vlist/features/index.ts +10 -0
  9. package/src/components/vlist/features/selection.ts +444 -0
  10. package/src/components/vlist/features/viewport.ts +65 -0
  11. package/src/components/vlist/index.ts +16 -0
  12. package/src/components/{list → vlist}/types.ts +104 -26
  13. package/src/components/vlist/vlist.ts +92 -0
  14. package/src/core/compose/features/gestures/index.ts +227 -0
  15. package/src/core/compose/features/gestures/longpress.ts +383 -0
  16. package/src/core/compose/features/gestures/pan.ts +424 -0
  17. package/src/core/compose/features/gestures/pinch.ts +475 -0
  18. package/src/core/compose/features/gestures/rotate.ts +485 -0
  19. package/src/core/compose/features/gestures/swipe.ts +492 -0
  20. package/src/core/compose/features/gestures/tap.ts +334 -0
  21. package/src/core/compose/features/index.ts +2 -38
  22. package/src/core/compose/index.ts +13 -29
  23. package/src/core/gestures/index.ts +31 -0
  24. package/src/core/gestures/longpress.ts +68 -0
  25. package/src/core/gestures/manager.ts +418 -0
  26. package/src/core/gestures/pan.ts +48 -0
  27. package/src/core/gestures/pinch.ts +58 -0
  28. package/src/core/gestures/rotate.ts +58 -0
  29. package/src/core/gestures/swipe.ts +66 -0
  30. package/src/core/gestures/tap.ts +45 -0
  31. package/src/core/gestures/types.ts +387 -0
  32. package/src/core/gestures/utils.ts +128 -0
  33. package/src/core/index.ts +27 -151
  34. package/src/core/layout/schema.ts +73 -35
  35. package/src/core/layout/types.ts +5 -2
  36. package/src/core/viewport/constants.ts +140 -0
  37. package/src/core/viewport/features/base.ts +73 -0
  38. package/src/core/viewport/features/collection.ts +882 -0
  39. package/src/core/viewport/features/events.ts +130 -0
  40. package/src/core/viewport/features/index.ts +20 -0
  41. package/src/core/{list-manager/features/viewport → viewport/features}/item-size.ts +27 -30
  42. package/src/core/{list-manager/features/viewport → viewport/features}/loading.ts +4 -4
  43. package/src/core/viewport/features/momentum.ts +260 -0
  44. package/src/core/viewport/features/placeholders.ts +335 -0
  45. package/src/core/viewport/features/rendering.ts +568 -0
  46. package/src/core/viewport/features/scrollbar.ts +434 -0
  47. package/src/core/viewport/features/scrolling.ts +618 -0
  48. package/src/core/viewport/features/utils.ts +88 -0
  49. package/src/core/viewport/features/virtual.ts +384 -0
  50. package/src/core/viewport/index.ts +31 -0
  51. package/src/core/viewport/types.ts +133 -0
  52. package/src/core/viewport/utils/speed-tracker.ts +79 -0
  53. package/src/core/viewport/viewport.ts +246 -0
  54. package/src/index.ts +0 -7
  55. package/src/styles/components/_vlist.scss +331 -0
  56. package/src/styles/index.scss +1 -1
  57. package/test/components/vlist-selection.test.ts +240 -0
  58. package/test/components/vlist.test.ts +63 -0
  59. package/test/core/collection/adapter.test.ts +161 -0
  60. package/bun.lock +0 -792
  61. package/src/components/list/api.ts +0 -314
  62. package/src/components/list/constants.ts +0 -56
  63. package/src/components/list/features/api.ts +0 -428
  64. package/src/components/list/features/index.ts +0 -31
  65. package/src/components/list/features/list-manager.ts +0 -502
  66. package/src/components/list/index.ts +0 -39
  67. package/src/components/list/list.ts +0 -234
  68. package/src/core/collection/base-collection.ts +0 -100
  69. package/src/core/collection/collection-composer.ts +0 -178
  70. package/src/core/collection/collection.ts +0 -745
  71. package/src/core/collection/constants.ts +0 -172
  72. package/src/core/collection/events.ts +0 -428
  73. package/src/core/collection/features/api/loading.ts +0 -279
  74. package/src/core/collection/features/operations/data-operations.ts +0 -147
  75. package/src/core/collection/index.ts +0 -104
  76. package/src/core/collection/state.ts +0 -497
  77. package/src/core/collection/types.ts +0 -404
  78. package/src/core/compose/features/collection.ts +0 -119
  79. package/src/core/compose/features/selection.ts +0 -213
  80. package/src/core/compose/features/styling.ts +0 -108
  81. package/src/core/list-manager/api.ts +0 -599
  82. package/src/core/list-manager/config.ts +0 -593
  83. package/src/core/list-manager/constants.ts +0 -268
  84. package/src/core/list-manager/features/api.ts +0 -58
  85. package/src/core/list-manager/features/collection/collection.ts +0 -705
  86. package/src/core/list-manager/features/collection/index.ts +0 -17
  87. package/src/core/list-manager/features/viewport/constants.ts +0 -42
  88. package/src/core/list-manager/features/viewport/index.ts +0 -16
  89. package/src/core/list-manager/features/viewport/placeholders.ts +0 -281
  90. package/src/core/list-manager/features/viewport/rendering.ts +0 -575
  91. package/src/core/list-manager/features/viewport/scrollbar.ts +0 -495
  92. package/src/core/list-manager/features/viewport/scrolling.ts +0 -795
  93. package/src/core/list-manager/features/viewport/template.ts +0 -220
  94. package/src/core/list-manager/features/viewport/viewport.ts +0 -654
  95. package/src/core/list-manager/features/viewport/virtual.ts +0 -309
  96. package/src/core/list-manager/index.ts +0 -279
  97. package/src/core/list-manager/list-manager.ts +0 -206
  98. package/src/core/list-manager/types.ts +0 -439
  99. package/src/core/list-manager/utils/calculations.ts +0 -290
  100. package/src/core/list-manager/utils/range-calculator.ts +0 -349
  101. package/src/core/list-manager/utils/speed-tracker.ts +0 -273
  102. package/src/styles/components/_list.scss +0 -244
  103. package/src/types/mtrl.d.ts +0 -6
  104. package/test/components/list.test.ts +0 -256
  105. package/test/core/collection/failed-ranges.test.ts +0 -270
  106. package/test/core/compose/features.test.ts +0 -183
  107. package/test/core/list-manager/features/collection.test.ts +0 -704
  108. package/test/core/list-manager/features/viewport.test.ts +0 -698
  109. package/test/core/list-manager/list-manager.test.ts +0 -593
  110. package/test/core/list-manager/utils/calculations.test.ts +0 -433
  111. package/test/core/list-manager/utils/range-calculator.test.ts +0 -569
  112. package/test/core/list-manager/utils/speed-tracker.test.ts +0 -530
  113. package/tsconfig.build.json +0 -14
  114. /package/src/components/{list → vlist}/features.ts +0 -0
  115. /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
- }