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,309 +0,0 @@
1
- /**
2
- * Virtual Scrolling Module - Core virtual scrolling calculations
3
- * Handles visible range calculation and total virtual size management
4
- */
5
-
6
- import type { ListManagerComponent, ItemRange } from "../../types";
7
- import type { ItemSizeManager } from "./item-size";
8
- // Removed calculateVisibleRangeUtil import - using unified index-based approach
9
-
10
- /**
11
- * Configuration for virtual scrolling
12
- */
13
- export interface VirtualConfig {
14
- orientation: "vertical" | "horizontal";
15
- overscan: number;
16
- onDimensionsChanged?: (data: {
17
- containerSize: number;
18
- totalVirtualSize: number;
19
- estimatedItemSize: number;
20
- totalItems: number;
21
- }) => void;
22
- }
23
-
24
- /**
25
- * Virtual scrolling state
26
- */
27
- export interface VirtualState {
28
- totalVirtualSize: number;
29
- containerSize: number;
30
- }
31
-
32
- /**
33
- * Virtual scrolling manager interface
34
- */
35
- export interface VirtualManager {
36
- // Range calculations
37
- calculateVisibleRange(scrollPosition: number): ItemRange;
38
-
39
- // Size management
40
- updateTotalVirtualSize(totalItems: number): void;
41
- getTotalVirtualSize(): number;
42
-
43
- // Index-based scrolling utilities
44
- calculateVirtualPositionForIndex(index: number): number;
45
- calculateIndexFromVirtualPosition(position: number): number;
46
- getMaxScrollPosition(): number;
47
-
48
- // State management
49
- updateState(updates: Partial<VirtualState>): void;
50
- getState(): VirtualState;
51
- }
52
-
53
- /**
54
- * Creates a virtual scrolling manager using index-based approach
55
- * This avoids browser height limitations by not creating massive DOM elements
56
- */
57
- export const createVirtualManager = (
58
- component: ListManagerComponent,
59
- itemSizeManager: ItemSizeManager,
60
- config: VirtualConfig,
61
- getTotalItems?: () => number
62
- ): VirtualManager => {
63
- const { orientation, overscan, onDimensionsChanged } = config;
64
-
65
- // Virtual scrolling state
66
- let totalVirtualSize = 0;
67
- let containerSize = 0;
68
-
69
- /**
70
- * Calculate visible range based on scroll position
71
- * Uses unified index-based approach for all dataset sizes
72
- */
73
- const calculateVisibleRange = (scrollPosition: number): ItemRange => {
74
- const actualTotalItems = getTotalItems
75
- ? getTotalItems()
76
- : component.totalItems;
77
-
78
- if (actualTotalItems === 0) {
79
- return { start: 0, end: 0 };
80
- }
81
-
82
- // Always use index-based calculation for consistency
83
- if (totalVirtualSize > 0) {
84
- // Map scroll position to item index using ratio
85
- const scrollRatio = Math.min(1, scrollPosition / totalVirtualSize);
86
- const exactScrollIndex = scrollRatio * actualTotalItems;
87
- const startIndex = Math.floor(exactScrollIndex);
88
-
89
- // Calculate viewport size in items
90
- const viewportItemCount = Math.ceil(
91
- containerSize / itemSizeManager.getEstimatedItemSize()
92
- );
93
- const itemsInViewport = Math.floor(
94
- containerSize / itemSizeManager.getEstimatedItemSize()
95
- );
96
-
97
- // Special handling for when we're near the very end
98
- const maxScrollPosition = totalVirtualSize - containerSize;
99
- const distanceFromBottom = maxScrollPosition - scrollPosition;
100
-
101
- // Calculate what the last possible start index should be
102
- const maxStartIndex = Math.max(0, actualTotalItems - itemsInViewport);
103
-
104
- // Use a larger threshold (500 pixels) to ensure smooth transitions
105
- // This represents about 6 items worth of scrolling
106
- const bottomThreshold = 500;
107
-
108
- if (distanceFromBottom <= bottomThreshold && distanceFromBottom >= -1) {
109
- // When near the bottom, interpolate between the calculated position and the last position
110
- // This ensures smooth scrolling without jumps
111
-
112
- if (distanceFromBottom <= 1 && distanceFromBottom >= -1) {
113
- // At the very bottom, show exactly the last items
114
- const lastStartIndex = maxStartIndex;
115
- const start = Math.max(0, lastStartIndex - overscan);
116
- const end = actualTotalItems - 1;
117
-
118
- return { start, end };
119
- } else {
120
- // Near the bottom but not at the very end
121
- // Smoothly interpolate between normal calculation and bottom position
122
- const interpolationFactor =
123
- (bottomThreshold - distanceFromBottom) / bottomThreshold;
124
-
125
- // Calculate where we would be with normal scrolling
126
- let normalStartIndex = startIndex;
127
- if (normalStartIndex > maxStartIndex) {
128
- normalStartIndex = maxStartIndex;
129
- }
130
-
131
- // Interpolate between normal position and max position
132
- const interpolatedStartIndex = Math.floor(
133
- normalStartIndex +
134
- (maxStartIndex - normalStartIndex) * interpolationFactor
135
- );
136
-
137
- const endIndex = Math.min(
138
- interpolatedStartIndex + viewportItemCount - 1,
139
- actualTotalItems - 1
140
- );
141
-
142
- // Apply overscan
143
- const start = Math.max(0, interpolatedStartIndex - overscan);
144
- const end = Math.min(actualTotalItems - 1, endIndex + overscan);
145
-
146
- return { start, end };
147
- }
148
- }
149
-
150
- // For positions not near the end, use normal index-based calculation
151
- let adjustedStartIndex = startIndex;
152
- if (startIndex > maxStartIndex) {
153
- adjustedStartIndex = maxStartIndex;
154
- }
155
-
156
- const endIndex = Math.min(
157
- adjustedStartIndex + viewportItemCount - 1,
158
- actualTotalItems - 1
159
- );
160
-
161
- // Apply overscan
162
- const start = Math.max(0, adjustedStartIndex - overscan);
163
- const end = Math.min(actualTotalItems - 1, endIndex + overscan);
164
-
165
- return { start, end };
166
- }
167
-
168
- // This should not happen as totalVirtualSize should always be > 0
169
- console.warn(
170
- `[VIRTUAL] Unexpected state: totalVirtualSize=${totalVirtualSize}`
171
- );
172
- return { start: 0, end: Math.min(10, actualTotalItems - 1) };
173
- };
174
-
175
- /**
176
- * Update total virtual size based on total items
177
- * Uses actual size when possible, caps at 10M pixels to prevent browser issues
178
- */
179
- const updateTotalVirtualSize = (totalItems: number): void => {
180
- const estimatedItemSize = itemSizeManager.getEstimatedItemSize();
181
-
182
- // Cap the virtual size at a reasonable maximum to prevent browser issues
183
- // This provides smooth scrolling for any dataset size
184
- const MAX_VIRTUAL_SIZE = 10 * 1000 * 1000; // 10M pixels - well within browser limits
185
-
186
- let newTotalVirtualSize: number;
187
-
188
- if (totalItems * estimatedItemSize > MAX_VIRTUAL_SIZE) {
189
- // Cap virtual size to prevent browser issues
190
- newTotalVirtualSize = MAX_VIRTUAL_SIZE;
191
- // console.log(
192
- // `📐 [VIRTUAL] Capping virtual size at 10M pixels for ${totalItems.toLocaleString()} items (would be ${(
193
- // (totalItems * estimatedItemSize) /
194
- // 1_000_000
195
- // ).toFixed(1)}M pixels)`
196
- // );
197
- } else {
198
- // Use actual size when within limits
199
- newTotalVirtualSize = totalItems * estimatedItemSize;
200
- }
201
-
202
- if (newTotalVirtualSize !== totalVirtualSize) {
203
- totalVirtualSize = newTotalVirtualSize;
204
-
205
- // Notify about dimensions change
206
- onDimensionsChanged?.({
207
- containerSize,
208
- totalVirtualSize: newTotalVirtualSize,
209
- estimatedItemSize,
210
- totalItems,
211
- });
212
- }
213
- };
214
-
215
- /**
216
- * Calculate virtual scroll position for a given item index
217
- */
218
- const calculateVirtualPositionForIndex = (index: number): number => {
219
- const actualTotalItems = getTotalItems
220
- ? getTotalItems()
221
- : component.totalItems;
222
-
223
- if (actualTotalItems === 0) return 0;
224
-
225
- const itemSize = itemSizeManager.getEstimatedItemSize();
226
- const actualPosition = index * itemSize;
227
-
228
- // If using index-based scrolling, map to virtual space
229
- const actualTotalSize = actualTotalItems * itemSize;
230
- if (actualTotalSize > totalVirtualSize) {
231
- const ratio = index / actualTotalItems;
232
- return ratio * totalVirtualSize;
233
- }
234
-
235
- return actualPosition;
236
- };
237
-
238
- /**
239
- * Calculate item index from virtual scroll position
240
- */
241
- const calculateIndexFromVirtualPosition = (position: number): number => {
242
- const actualTotalItems = getTotalItems
243
- ? getTotalItems()
244
- : component.totalItems;
245
-
246
- if (actualTotalItems === 0 || totalVirtualSize === 0) return 0;
247
-
248
- const itemSize = itemSizeManager.getEstimatedItemSize();
249
- const actualTotalSize = actualTotalItems * itemSize;
250
-
251
- // If using index-based scrolling, map from virtual space
252
- if (actualTotalSize > totalVirtualSize) {
253
- const ratio = position / totalVirtualSize;
254
- return Math.floor(ratio * actualTotalItems);
255
- }
256
-
257
- return Math.floor(position / itemSize);
258
- };
259
-
260
- /**
261
- * Get maximum scroll position
262
- */
263
- const getMaxScrollPosition = (): number => {
264
- return Math.max(0, totalVirtualSize - containerSize);
265
- };
266
-
267
- /**
268
- * Get current total virtual size
269
- */
270
- const getTotalVirtualSize = (): number => totalVirtualSize;
271
-
272
- /**
273
- * Update virtual scrolling state
274
- */
275
- const updateState = (updates: Partial<VirtualState>): void => {
276
- if (updates.totalVirtualSize !== undefined) {
277
- totalVirtualSize = updates.totalVirtualSize;
278
- }
279
- if (updates.containerSize !== undefined) {
280
- containerSize = updates.containerSize;
281
- }
282
- };
283
-
284
- /**
285
- * Get current virtual scrolling state
286
- */
287
- const getState = (): VirtualState => ({
288
- totalVirtualSize,
289
- containerSize,
290
- });
291
-
292
- return {
293
- // Range calculations
294
- calculateVisibleRange,
295
-
296
- // Size management
297
- updateTotalVirtualSize,
298
- getTotalVirtualSize,
299
-
300
- // Index-based scrolling utilities
301
- calculateVirtualPositionForIndex,
302
- calculateIndexFromVirtualPosition,
303
- getMaxScrollPosition,
304
-
305
- // State management
306
- updateState,
307
- getState,
308
- };
309
- };
@@ -1,279 +0,0 @@
1
- /**
2
- * List Manager Public API
3
- * Main exports for the mtrl-addons List Manager system
4
- */
5
-
6
- // Import types first
7
- import type {
8
- ListManager,
9
- ListManagerConfig,
10
- CollectionConfig,
11
- ItemRange,
12
- ViewportInfo,
13
- } from "./types";
14
- import { createListManager } from "./list-manager";
15
- import { createListManagerAPI, ListManagerAPI, ListManagerUtils } from "./api";
16
-
17
- // Export all types
18
- export type {
19
- ListManager,
20
- ListManagerConfig,
21
- ListManagerConfigUpdate,
22
- ListManagerObserver,
23
- ListManagerUnsubscribe,
24
- ItemRange,
25
- ViewportInfo,
26
- SpeedTracker,
27
- ViewportFeature,
28
- CollectionFeature,
29
- FeatureContext,
30
- RangeCalculationResult,
31
-
32
- // Configuration types
33
- CollectionConfig,
34
- TemplateConfig,
35
- VirtualConfig,
36
- OrientationConfig,
37
- InitialLoadConfig,
38
- ErrorHandlingConfig,
39
- PositioningConfig,
40
- BoundariesConfig,
41
- RecyclingConfig,
42
- PerformanceConfig,
43
- IntersectionConfig,
44
-
45
- // Event system
46
- ListManagerEventData,
47
- } from "./types";
48
-
49
- export { ListManagerEvents } from "./types";
50
-
51
- // Export core functions
52
- export { createListManager, ListManagerImpl } from "./list-manager";
53
- export { createListManagerAPI, ListManagerAPI, ListManagerUtils } from "./api";
54
-
55
- // Export constants
56
- export { LIST_MANAGER_CONSTANTS, mergeConstants } from "./constants";
57
- export type { ListManagerConstants } from "./constants";
58
-
59
- // Export utility functions
60
- export {
61
- calculateTotalVirtualSize,
62
- calculateContainerPosition,
63
- calculateScrollPositionForIndex,
64
- calculateScrollPositionForPage,
65
- calculateScrollbarMetrics,
66
- calculateInitialRangeSize,
67
- calculateMissingRanges,
68
- calculateBufferRanges,
69
- clamp,
70
- applyBoundaryResistance,
71
- } from "./utils/calculations";
72
-
73
- export {
74
- createSpeedTracker,
75
- updateSpeedTracker,
76
- isFastScrolling,
77
- isSlowScrolling,
78
- getLoadingStrategy,
79
- calculateScrollMomentum,
80
- createSpeedBasedLoadingConfig,
81
- resetSpeedTracker,
82
- getScrollThrottleInterval,
83
- hasSignificantDirectionChange,
84
- calculateAdaptiveOverscan,
85
- getSpeedTrackerDebugInfo,
86
- } from "./utils/speed-tracker";
87
-
88
- export {
89
- calculateRangeIndex,
90
- calculateRangeBounds,
91
- calculateRequiredRanges,
92
- calculatePrefetchRanges,
93
- calculateRangeResult,
94
- rangeToPaginationParams,
95
- rangesToBatchParams,
96
- calculateOptimalRangeSize,
97
- isRangeInViewport,
98
- calculateRangePriority,
99
- sortRangesByPriority,
100
- mergeAdjacentRanges,
101
- calculateRangeCleanupCandidates,
102
- calculateRangeLoadingOrder,
103
- getRangeDebugInfo,
104
- } from "./utils/range-calculator";
105
-
106
- // Export feature factories
107
- export { createViewportFeature } from "./features/viewport";
108
- export { createCollectionFeature } from "./features/collection";
109
-
110
- /**
111
- * Default export - createListManager for convenience
112
- */
113
- export { createListManager as default } from "./list-manager";
114
-
115
- /**
116
- * Version information
117
- */
118
- export const LIST_MANAGER_VERSION = "1.0.0";
119
-
120
- /**
121
- * Feature compatibility flags
122
- */
123
- export const FEATURES = {
124
- VIRTUAL_SCROLLING: true,
125
- CUSTOM_SCROLLBAR: true,
126
- SPEED_BASED_LOADING: true,
127
- PLACEHOLDER_SYSTEM: true,
128
- ORIENTATION_SUPPORT: true,
129
- RANGE_PAGINATION: true,
130
- ELEMENT_RECYCLING: false, // Phase 2
131
- SMOOTH_SCROLLING: false, // Phase 2
132
- PERFORMANCE_MONITORING: false, // Phase 2
133
- } as const;
134
-
135
- /**
136
- * Quick setup helpers for common use cases
137
- */
138
- export const QuickSetup = {
139
- /**
140
- * Create a basic vertical list with static items
141
- */
142
- verticalList: (
143
- container: HTMLElement,
144
- items: any[],
145
- template: (item: any, index: number) => HTMLElement
146
- ): ListManager => {
147
- return createListManager({
148
- container,
149
- items,
150
- template: { template },
151
- virtual: {
152
- enabled: true,
153
- itemSize: "auto",
154
- estimatedItemSize: 84,
155
- overscan: 5,
156
- },
157
- orientation: {
158
- orientation: "vertical",
159
- reverse: false,
160
- crossAxisAlignment: "stretch",
161
- },
162
- debug: false,
163
- prefix: "mtrl-list",
164
- componentName: "List",
165
- });
166
- },
167
-
168
- /**
169
- * Create a horizontal list with static items
170
- */
171
- horizontalList: (
172
- container: HTMLElement,
173
- items: any[],
174
- template: (item: any, index: number) => HTMLElement
175
- ): ListManager => {
176
- return createListManager({
177
- container,
178
- items,
179
- template: { template },
180
- virtual: {
181
- enabled: true,
182
- itemSize: "auto",
183
- estimatedItemSize: 200,
184
- overscan: 3,
185
- },
186
- orientation: {
187
- orientation: "horizontal",
188
- reverse: false,
189
- crossAxisAlignment: "stretch",
190
- },
191
- debug: false,
192
- prefix: "mtrl-list",
193
- componentName: "HorizontalList",
194
- });
195
- },
196
-
197
- /**
198
- * Create an API-driven list with collection integration
199
- */
200
- apiList: (
201
- container: HTMLElement,
202
- collection: CollectionConfig,
203
- template: (item: any, index: number) => HTMLElement
204
- ): ListManager => {
205
- return createListManager({
206
- container,
207
- collection,
208
- template: { template },
209
- virtual: {
210
- enabled: true,
211
- itemSize: "auto",
212
- estimatedItemSize: 60,
213
- overscan: 5,
214
- },
215
- orientation: {
216
- orientation: "vertical",
217
- reverse: false,
218
- crossAxisAlignment: "stretch",
219
- },
220
- initialLoad: {
221
- strategy: "placeholders",
222
- viewportMultiplier: 1.5,
223
- minItems: 10,
224
- maxItems: 100,
225
- },
226
- debug: false,
227
- prefix: "mtrl-list",
228
- componentName: "ApiList",
229
- });
230
- },
231
-
232
- /**
233
- * Create a debug list for development
234
- */
235
- debugList: (
236
- container: HTMLElement,
237
- itemCount: number = 1000
238
- ): ListManagerAPI => {
239
- return createListManagerAPI(
240
- ListManagerUtils.createTestConfig(container, itemCount)
241
- );
242
- },
243
- };
244
-
245
- /**
246
- * Type guards for feature detection
247
- */
248
- export const TypeGuards = {
249
- isListManager: (obj: any): obj is ListManager => {
250
- return (
251
- obj &&
252
- typeof obj.scrollToIndex === "function" &&
253
- typeof obj.getVisibleRange === "function" &&
254
- typeof obj.initialize === "function"
255
- );
256
- },
257
-
258
- isListManagerAPI: (obj: any): obj is ListManagerAPI => {
259
- return (
260
- TypeGuards.isListManager(obj) &&
261
- typeof obj.onScroll === "function" &&
262
- typeof obj.getDebugInfo === "function"
263
- );
264
- },
265
-
266
- isItemRange: (obj: any): obj is ItemRange => {
267
- return obj && typeof obj.start === "number" && typeof obj.end === "number";
268
- },
269
-
270
- isViewportInfo: (obj: any): obj is ViewportInfo => {
271
- return (
272
- obj &&
273
- typeof obj.containerSize === "number" &&
274
- typeof obj.totalVirtualSize === "number" &&
275
- TypeGuards.isItemRange(obj.visibleRange) &&
276
- typeof obj.virtualScrollPosition === "number"
277
- );
278
- },
279
- };