mtrl-addons 0.1.2 → 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 -86
  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 -23
  114. /package/src/components/{list → vlist}/features.ts +0 -0
  115. /package/src/core/{compose → viewport}/features/performance.ts +0 -0
@@ -1,172 +0,0 @@
1
- /**
2
- * Constants for the mtrl-addons collection system (Pure Data Layer)
3
- *
4
- * Data-related constants only - NO UI constants
5
- */
6
-
7
- /**
8
- * Data pagination constants
9
- */
10
- export const DATA_PAGINATION = {
11
- DEFAULT_PAGE_SIZE: 20,
12
- DEFAULT_CURRENT_PAGE: 1,
13
- MAX_PREFETCH_PAGES: 5,
14
- MIN_PAGE_SIZE: 1,
15
- MAX_PAGE_SIZE: 1000,
16
- } as const;
17
-
18
- /**
19
- * Data caching constants
20
- */
21
- export const DATA_CACHE = {
22
- DEFAULT_MAX_SIZE: 1000,
23
- DEFAULT_MAX_AGE: 60 * 60 * 1000, // 1 hour
24
- CLEANUP_INTERVAL: 5 * 60 * 1000, // 5 minutes
25
- DEFAULT_STRATEGY: "memory",
26
- LRU_DEFAULT_SIZE: 500,
27
- } as const;
28
-
29
- /**
30
- * Data persistence constants
31
- */
32
- export const DATA_PERSISTENCE = {
33
- DEFAULT_KEY_PREFIX: "mtrl-collection-",
34
- DEFAULT_VERSION: 1,
35
- SYNC_DEBOUNCE: 1000, // 1 second
36
- DEFAULT_STRATEGY: "localStorage",
37
- MAX_LOCALSTORAGE_SIZE: 5 * 1024 * 1024, // 5MB
38
- INDEXED_DB_VERSION: 1,
39
- } as const;
40
-
41
- /**
42
- * Web worker constants
43
- */
44
- export const WEB_WORKERS = {
45
- MAX_WORKERS:
46
- typeof navigator !== "undefined" ? navigator.hardwareConcurrency || 4 : 4,
47
- TASK_TIMEOUT: 30000, // 30 seconds
48
- CHUNK_SIZE: 1000, // Items per worker task
49
- DEFAULT_PRIORITY: "normal",
50
- RETRY_ATTEMPTS: 3,
51
- RETRY_DELAY: 1000, // 1 second
52
- } as const;
53
-
54
- /**
55
- * Data validation constants
56
- */
57
- export const DATA_VALIDATION = {
58
- DEFAULT_STRICT_MODE: false,
59
- MAX_VALIDATION_ERRORS: 100,
60
- VALIDATION_TIMEOUT: 5000, // 5 seconds
61
- DEFAULT_SANITIZE: true,
62
- } as const;
63
-
64
- /**
65
- * Data transformation constants
66
- */
67
- export const DATA_TRANSFORMATION = {
68
- MAX_TRANSFORM_TIME: 10000, // 10 seconds
69
- BATCH_SIZE: 500,
70
- DEFAULT_NORMALIZE: true,
71
- MAX_DEPTH: 10, // For nested object transformation
72
- } as const;
73
-
74
- /**
75
- * API adapter constants
76
- */
77
- export const API_ADAPTER = {
78
- DEFAULT_TIMEOUT: 30000, // 30 seconds
79
- RETRY_ATTEMPTS: 3,
80
- RETRY_DELAY: 1000, // 1 second
81
- MAX_CONCURRENT_REQUESTS: 5,
82
- DEFAULT_HEADERS: {
83
- "Content-Type": "application/json",
84
- },
85
- } as const;
86
-
87
- /**
88
- * Background processing constants
89
- */
90
- export const BACKGROUND_PROCESSING = {
91
- PREFETCH_THRESHOLD: 0.8, // Start prefetching when 80% through current data
92
- MAX_PREFETCH_QUEUE: 10,
93
- PREFETCH_DEBOUNCE: 500, // 500ms
94
- BACKGROUND_SYNC_INTERVAL: 30000, // 30 seconds
95
- } as const;
96
-
97
- /**
98
- * Data logging constants
99
- */
100
- export const DATA_LOGGING = {
101
- PREFIX: "[COLLECTION]",
102
- LEVELS: {
103
- ERROR: "ERROR",
104
- WARN: "WARN",
105
- INFO: "INFO",
106
- DEBUG: "DEBUG",
107
- },
108
- ENABLE_DEBUG: false, // Set to true for development
109
- } as const;
110
-
111
- /**
112
- * Collection state constants
113
- */
114
- export const COLLECTION_STATE = {
115
- INITIAL_SIZE: 0,
116
- INITIAL_PAGE: 1,
117
- INITIAL_LOADING: false,
118
- INITIAL_ERROR: null,
119
- INITIAL_HAS_MORE: true,
120
- } as const;
121
-
122
- /**
123
- * Data event timing constants
124
- */
125
- export const EVENT_TIMING = {
126
- DEBOUNCE_DELAY: 100, // 100ms
127
- THROTTLE_DELAY: 16, // ~60fps
128
- EMIT_TIMEOUT: 5000, // 5 seconds
129
- MAX_LISTENERS: 100,
130
- } as const;
131
-
132
- /**
133
- * Data aggregation constants
134
- */
135
- export const DATA_AGGREGATION = {
136
- SUPPORTED_OPERATIONS: [
137
- "sum",
138
- "count",
139
- "avg",
140
- "min",
141
- "max",
142
- "distinct",
143
- ] as const,
144
- MAX_FIELD_DEPTH: 5,
145
- AGGREGATION_TIMEOUT: 10000, // 10 seconds
146
- } as const;
147
-
148
- /**
149
- * Data search constants
150
- */
151
- export const DATA_SEARCH = {
152
- DEFAULT_FIELDS: ["id"],
153
- MAX_SEARCH_FIELDS: 20,
154
- SEARCH_DEBOUNCE: 300, // 300ms
155
- MIN_SEARCH_LENGTH: 1,
156
- MAX_SEARCH_LENGTH: 1000,
157
- } as const;
158
-
159
- /**
160
- * Collection defaults for initialization
161
- */
162
- export const COLLECTION_DEFAULTS = {
163
- PAGE_SIZE: DATA_PAGINATION.DEFAULT_PAGE_SIZE,
164
- CURRENT_PAGE: DATA_PAGINATION.DEFAULT_CURRENT_PAGE,
165
- CACHE_STRATEGY: DATA_CACHE.DEFAULT_STRATEGY,
166
- PERSISTENCE_STRATEGY: DATA_PERSISTENCE.DEFAULT_STRATEGY,
167
- WEB_WORKERS_ENABLED: false,
168
- VALIDATION_STRICT: DATA_VALIDATION.DEFAULT_STRICT_MODE,
169
- PREFETCH_ENABLED: false,
170
- } as const;
171
-
172
- // NO UI constants: STYLING, DOM, TEMPLATE, SCROLL, INTERSECTION - those belong to List Manager/Component
@@ -1,428 +0,0 @@
1
- /**
2
- * Event system for mtrl-addons collection (Pure Data Layer)
3
- *
4
- * Handles data-focused events with zero UI concerns
5
- */
6
-
7
- import type {
8
- CollectionItem,
9
- CollectionObserver,
10
- CollectionUnsubscribe,
11
- CollectionEventPayload,
12
- CollectionDataEvents,
13
- } from "./types";
14
- import { DATA_LOGGING, EVENT_TIMING } from "./constants";
15
-
16
- /**
17
- * Data-focused collection events (NO UI EVENTS)
18
- */
19
- export const CollectionEvents = {
20
- // Data lifecycle events
21
- ITEMS_LOADED: "items:loaded" as const,
22
- ITEMS_ADDED: "items:added" as const,
23
- ITEMS_UPDATED: "items:updated" as const,
24
- ITEMS_REMOVED: "items:removed" as const,
25
- ITEMS_CLEARED: "items:cleared" as const,
26
-
27
- // Data state events
28
- LOADING_START: "loading:start" as const,
29
- LOADING_END: "loading:end" as const,
30
- ERROR_OCCURRED: "error:occurred" as const,
31
-
32
- // Data operations events
33
- CACHE_HIT: "cache:hit" as const,
34
- CACHE_MISS: "cache:miss" as const,
35
- CACHE_CLEARED: "cache:cleared" as const,
36
- SYNC_START: "sync:start" as const,
37
- SYNC_COMPLETE: "sync:complete" as const,
38
-
39
- // Background operations events
40
- PREFETCH_START: "prefetch:start" as const,
41
- PREFETCH_COMPLETE: "prefetch:complete" as const,
42
- WORKER_TASK_START: "worker:task:start" as const,
43
- WORKER_TASK_COMPLETE: "worker:task:complete" as const,
44
-
45
- // Data validation events
46
- VALIDATION_START: "validation:start" as const,
47
- VALIDATION_COMPLETE: "validation:complete" as const,
48
- VALIDATION_ERROR: "validation:error" as const,
49
-
50
- // Data transformation events
51
- TRANSFORM_START: "transform:start" as const,
52
- TRANSFORM_COMPLETE: "transform:complete" as const,
53
- TRANSFORM_ERROR: "transform:error" as const,
54
-
55
- // Data persistence events
56
- SAVE_START: "save:start" as const,
57
- SAVE_COMPLETE: "save:complete" as const,
58
- SAVE_ERROR: "save:error" as const,
59
- LOAD_START: "load:start" as const,
60
- LOAD_COMPLETE: "load:complete" as const,
61
- LOAD_ERROR: "load:error" as const,
62
-
63
- // NO UI events: render:start, scroll:changed, viewport:changed, etc.
64
- } as const;
65
-
66
- /**
67
- * Collection event emitter interface
68
- */
69
- export interface CollectionEventEmitter<
70
- T extends CollectionItem = CollectionItem
71
- > {
72
- subscribe(observer: CollectionObserver<T>): CollectionUnsubscribe;
73
- emit(event: CollectionDataEvents, data?: any): void;
74
- removeAllListeners(): void;
75
- getListenerCount(): number;
76
- destroy(): void;
77
- }
78
-
79
- /**
80
- * Creates a data-focused event emitter for collection
81
- */
82
- export function createCollectionEventEmitter<
83
- T extends CollectionItem = CollectionItem
84
- >(): CollectionEventEmitter<T> {
85
- const listeners = new Map<string, Set<CollectionObserver<T>>>();
86
- let isDestroyed = false;
87
-
88
- /**
89
- * Subscribe to data events
90
- */
91
- const subscribe = (
92
- observer: CollectionObserver<T>
93
- ): CollectionUnsubscribe => {
94
- if (isDestroyed) {
95
- console.warn(
96
- `${DATA_LOGGING.PREFIX} Cannot subscribe to destroyed event emitter`
97
- );
98
- return () => {};
99
- }
100
-
101
- // Validate observer
102
- if (typeof observer !== "function") {
103
- throw new Error("Observer must be a function");
104
- }
105
-
106
- // Check listener limit
107
- const totalListeners = Array.from(listeners.values()).reduce(
108
- (sum, set) => sum + set.size,
109
- 0
110
- );
111
-
112
- if (totalListeners >= EVENT_TIMING.MAX_LISTENERS) {
113
- console.warn(
114
- `${DATA_LOGGING.PREFIX} Maximum listeners (${EVENT_TIMING.MAX_LISTENERS}) reached`
115
- );
116
- }
117
-
118
- // Add observer to all data events
119
- Object.values(CollectionEvents).forEach((event) => {
120
- if (!listeners.has(event)) {
121
- listeners.set(event, new Set());
122
- }
123
- listeners.get(event)!.add(observer);
124
- });
125
-
126
- // Return unsubscribe function
127
- return () => {
128
- Object.values(CollectionEvents).forEach((event) => {
129
- const eventListeners = listeners.get(event);
130
- if (eventListeners) {
131
- eventListeners.delete(observer);
132
- if (eventListeners.size === 0) {
133
- listeners.delete(event);
134
- }
135
- }
136
- });
137
- };
138
- };
139
-
140
- /**
141
- * Emit data events to subscribers
142
- */
143
- const emit = (event: CollectionDataEvents, data?: any): void => {
144
- if (isDestroyed) {
145
- console.warn(
146
- `${DATA_LOGGING.PREFIX} Cannot emit on destroyed event emitter`
147
- );
148
- return;
149
- }
150
-
151
- const eventListeners = listeners.get(event);
152
- if (!eventListeners || eventListeners.size === 0) {
153
- return; // No listeners for this event
154
- }
155
-
156
- const payload: CollectionEventPayload<T> = {
157
- event,
158
- data,
159
- timestamp: Date.now(),
160
- source: "collection",
161
- };
162
-
163
- // Emit to all listeners with error handling
164
- eventListeners.forEach((observer) => {
165
- try {
166
- // Use timeout to prevent blocking
167
- const timeoutId = setTimeout(() => {
168
- observer(payload);
169
- }, 0);
170
-
171
- // Clear timeout after emit timeout
172
- setTimeout(() => {
173
- clearTimeout(timeoutId);
174
- }, EVENT_TIMING.EMIT_TIMEOUT);
175
- } catch (error) {
176
- console.error(`${DATA_LOGGING.PREFIX} Error in event observer:`, error);
177
-
178
- // Remove problematic observer
179
- eventListeners.delete(observer);
180
-
181
- // Emit error event
182
- if (event !== CollectionEvents.ERROR_OCCURRED) {
183
- emit(CollectionEvents.ERROR_OCCURRED, {
184
- error,
185
- originalEvent: event,
186
- observer: observer.name || "anonymous",
187
- });
188
- }
189
- }
190
- });
191
-
192
- // Debug logging
193
- if (DATA_LOGGING.ENABLE_DEBUG) {
194
- console.log(`${DATA_LOGGING.PREFIX} Event emitted:`, {
195
- event,
196
- data,
197
- listenerCount: eventListeners.size,
198
- });
199
- }
200
- };
201
-
202
- /**
203
- * Remove all listeners
204
- */
205
- const removeAllListeners = (): void => {
206
- listeners.clear();
207
- };
208
-
209
- /**
210
- * Get total listener count
211
- */
212
- const getListenerCount = (): number => {
213
- return Array.from(listeners.values()).reduce(
214
- (sum, set) => sum + set.size,
215
- 0
216
- );
217
- };
218
-
219
- /**
220
- * Destroy the event emitter
221
- */
222
- const destroy = (): void => {
223
- removeAllListeners();
224
- isDestroyed = true;
225
- };
226
-
227
- return {
228
- subscribe,
229
- emit,
230
- removeAllListeners,
231
- getListenerCount,
232
- destroy,
233
- };
234
- }
235
-
236
- /**
237
- * Event payload factory functions for type safety
238
- */
239
- export const createEventPayload = {
240
- itemsLoaded: <T extends CollectionItem>(
241
- items: T[],
242
- meta?: any
243
- ): CollectionEventPayload<T> => ({
244
- event: CollectionEvents.ITEMS_LOADED,
245
- data: { items, meta },
246
- items,
247
- timestamp: Date.now(),
248
- source: "collection",
249
- }),
250
-
251
- itemsAdded: <T extends CollectionItem>(
252
- items: T[],
253
- indices: number[]
254
- ): CollectionEventPayload<T> => ({
255
- event: CollectionEvents.ITEMS_ADDED,
256
- data: { items, indices },
257
- items,
258
- timestamp: Date.now(),
259
- source: "collection",
260
- }),
261
-
262
- itemsUpdated: <T extends CollectionItem>(
263
- items: T[],
264
- indices: number[]
265
- ): CollectionEventPayload<T> => ({
266
- event: CollectionEvents.ITEMS_UPDATED,
267
- data: { items, indices },
268
- items,
269
- timestamp: Date.now(),
270
- source: "collection",
271
- }),
272
-
273
- itemsRemoved: <T extends CollectionItem>(
274
- ids: string[]
275
- ): CollectionEventPayload<T> => ({
276
- event: CollectionEvents.ITEMS_REMOVED,
277
- data: { ids },
278
- timestamp: Date.now(),
279
- source: "collection",
280
- }),
281
-
282
- loadingStart: <T extends CollectionItem>(
283
- reason: string
284
- ): CollectionEventPayload<T> => ({
285
- event: CollectionEvents.LOADING_START,
286
- data: { reason },
287
- timestamp: Date.now(),
288
- source: "collection",
289
- }),
290
-
291
- loadingEnd: <T extends CollectionItem>(
292
- reason: string
293
- ): CollectionEventPayload<T> => ({
294
- event: CollectionEvents.LOADING_END,
295
- data: { reason },
296
- timestamp: Date.now(),
297
- source: "collection",
298
- }),
299
-
300
- errorOccurred: <T extends CollectionItem>(
301
- error: Error,
302
- context?: any
303
- ): CollectionEventPayload<T> => ({
304
- event: CollectionEvents.ERROR_OCCURRED,
305
- data: { error, context },
306
- error,
307
- timestamp: Date.now(),
308
- source: "collection",
309
- }),
310
-
311
- cacheHit: <T extends CollectionItem>(
312
- key: string,
313
- size: number
314
- ): CollectionEventPayload<T> => ({
315
- event: CollectionEvents.CACHE_HIT,
316
- data: { key, size },
317
- timestamp: Date.now(),
318
- source: "collection",
319
- }),
320
-
321
- cacheMiss: <T extends CollectionItem>(
322
- key: string
323
- ): CollectionEventPayload<T> => ({
324
- event: CollectionEvents.CACHE_MISS,
325
- data: { key },
326
- timestamp: Date.now(),
327
- source: "collection",
328
- }),
329
-
330
- workerTaskStart: <T extends CollectionItem>(
331
- operation: string,
332
- itemCount: number
333
- ): CollectionEventPayload<T> => ({
334
- event: CollectionEvents.WORKER_TASK_START,
335
- data: { operation, itemCount },
336
- timestamp: Date.now(),
337
- source: "collection",
338
- }),
339
-
340
- workerTaskComplete: <T extends CollectionItem>(
341
- operation: string,
342
- duration: number,
343
- result?: any
344
- ): CollectionEventPayload<T> => ({
345
- event: CollectionEvents.WORKER_TASK_COMPLETE,
346
- data: { operation, duration, result },
347
- timestamp: Date.now(),
348
- source: "collection",
349
- }),
350
-
351
- prefetchStart: <T extends CollectionItem>(
352
- pages: number[]
353
- ): CollectionEventPayload<T> => ({
354
- event: CollectionEvents.PREFETCH_START,
355
- data: { pages },
356
- timestamp: Date.now(),
357
- source: "collection",
358
- }),
359
-
360
- prefetchComplete: <T extends CollectionItem>(
361
- items: T[],
362
- pages: number[]
363
- ): CollectionEventPayload<T> => ({
364
- event: CollectionEvents.PREFETCH_COMPLETE,
365
- data: { items, pages },
366
- items,
367
- timestamp: Date.now(),
368
- source: "collection",
369
- }),
370
- };
371
-
372
- /**
373
- * Event utilities for debugging and monitoring
374
- */
375
- export const eventUtils = {
376
- /**
377
- * Log event for debugging
378
- */
379
- logEvent: <T extends CollectionItem>(
380
- payload: CollectionEventPayload<T>
381
- ): void => {
382
- if (DATA_LOGGING.ENABLE_DEBUG) {
383
- console.log(`${DATA_LOGGING.PREFIX} ${payload.event}:`, {
384
- data: payload.data,
385
- timestamp: new Date(payload.timestamp).toISOString(),
386
- source: payload.source,
387
- });
388
- }
389
- },
390
-
391
- /**
392
- * Check if event is a data lifecycle event
393
- */
394
- isDataLifecycleEvent: (event: string): boolean => {
395
- return [
396
- CollectionEvents.ITEMS_LOADED,
397
- CollectionEvents.ITEMS_ADDED,
398
- CollectionEvents.ITEMS_UPDATED,
399
- CollectionEvents.ITEMS_REMOVED,
400
- CollectionEvents.ITEMS_CLEARED,
401
- ].includes(event as any);
402
- },
403
-
404
- /**
405
- * Check if event is a background operation event
406
- */
407
- isBackgroundEvent: (event: string): boolean => {
408
- return [
409
- CollectionEvents.PREFETCH_START,
410
- CollectionEvents.PREFETCH_COMPLETE,
411
- CollectionEvents.WORKER_TASK_START,
412
- CollectionEvents.WORKER_TASK_COMPLETE,
413
- ].includes(event as any);
414
- },
415
-
416
- /**
417
- * Check if event is an error event
418
- */
419
- isErrorEvent: (event: string): boolean => {
420
- return [
421
- CollectionEvents.ERROR_OCCURRED,
422
- CollectionEvents.VALIDATION_ERROR,
423
- CollectionEvents.TRANSFORM_ERROR,
424
- CollectionEvents.SAVE_ERROR,
425
- CollectionEvents.LOAD_ERROR,
426
- ].includes(event as any);
427
- },
428
- };