mtrl-addons 0.1.0 → 0.1.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 (92) hide show
  1. package/.cursorrules +117 -0
  2. package/AI.md +241 -0
  3. package/build.js +170 -0
  4. package/bun.lock +792 -0
  5. package/index.ts +7 -0
  6. package/package.json +10 -17
  7. package/scripts/analyze-orphaned-functions.ts +387 -0
  8. package/src/components/index.ts +45 -0
  9. package/src/components/list/api.ts +314 -0
  10. package/src/components/list/config.ts +352 -0
  11. package/src/components/list/constants.ts +56 -0
  12. package/src/components/list/features/api.ts +428 -0
  13. package/src/components/list/features/index.ts +31 -0
  14. package/src/components/list/features/list-manager.ts +502 -0
  15. package/src/components/list/features.ts +112 -0
  16. package/src/components/list/index.ts +39 -0
  17. package/src/components/list/list.ts +234 -0
  18. package/src/components/list/types.ts +513 -0
  19. package/src/core/collection/base-collection.ts +100 -0
  20. package/src/core/collection/collection-composer.ts +178 -0
  21. package/src/core/collection/collection.ts +745 -0
  22. package/src/core/collection/constants.ts +172 -0
  23. package/src/core/collection/events.ts +428 -0
  24. package/src/core/collection/features/api/loading.ts +279 -0
  25. package/src/core/collection/features/operations/data-operations.ts +147 -0
  26. package/src/core/collection/index.ts +104 -0
  27. package/src/core/collection/state.ts +497 -0
  28. package/src/core/collection/types.ts +404 -0
  29. package/src/core/compose/features/collection.ts +119 -0
  30. package/src/core/compose/features/index.ts +39 -0
  31. package/src/core/compose/features/performance.ts +161 -0
  32. package/src/core/compose/features/selection.ts +213 -0
  33. package/src/core/compose/features/styling.ts +108 -0
  34. package/src/core/compose/index.ts +31 -0
  35. package/src/core/index.ts +167 -0
  36. package/src/core/layout/config.ts +102 -0
  37. package/src/core/layout/index.ts +168 -0
  38. package/src/core/layout/jsx.ts +174 -0
  39. package/src/core/layout/schema.ts +963 -0
  40. package/src/core/layout/types.ts +92 -0
  41. package/src/core/list-manager/api.ts +599 -0
  42. package/src/core/list-manager/config.ts +593 -0
  43. package/src/core/list-manager/constants.ts +268 -0
  44. package/src/core/list-manager/features/api.ts +58 -0
  45. package/src/core/list-manager/features/collection/collection.ts +705 -0
  46. package/src/core/list-manager/features/collection/index.ts +17 -0
  47. package/src/core/list-manager/features/viewport/constants.ts +42 -0
  48. package/src/core/list-manager/features/viewport/index.ts +16 -0
  49. package/src/core/list-manager/features/viewport/item-size.ts +274 -0
  50. package/src/core/list-manager/features/viewport/loading.ts +263 -0
  51. package/src/core/list-manager/features/viewport/placeholders.ts +281 -0
  52. package/src/core/list-manager/features/viewport/rendering.ts +575 -0
  53. package/src/core/list-manager/features/viewport/scrollbar.ts +495 -0
  54. package/src/core/list-manager/features/viewport/scrolling.ts +795 -0
  55. package/src/core/list-manager/features/viewport/template.ts +220 -0
  56. package/src/core/list-manager/features/viewport/viewport.ts +654 -0
  57. package/src/core/list-manager/features/viewport/virtual.ts +309 -0
  58. package/src/core/list-manager/index.ts +279 -0
  59. package/src/core/list-manager/list-manager.ts +206 -0
  60. package/src/core/list-manager/types.ts +439 -0
  61. package/src/core/list-manager/utils/calculations.ts +290 -0
  62. package/src/core/list-manager/utils/range-calculator.ts +349 -0
  63. package/src/core/list-manager/utils/speed-tracker.ts +273 -0
  64. package/src/index.ts +17 -0
  65. package/src/styles/components/_list.scss +244 -0
  66. package/src/styles/index.scss +12 -0
  67. package/src/types/mtrl.d.ts +6 -0
  68. package/test/benchmarks/layout/advanced.test.ts +656 -0
  69. package/test/benchmarks/layout/comparison.test.ts +519 -0
  70. package/test/benchmarks/layout/performance-comparison.test.ts +274 -0
  71. package/test/benchmarks/layout/real-components.test.ts +733 -0
  72. package/test/benchmarks/layout/simple.test.ts +321 -0
  73. package/test/benchmarks/layout/stress.test.ts +990 -0
  74. package/test/collection/basic.test.ts +304 -0
  75. package/test/components/list.test.ts +256 -0
  76. package/test/core/collection/collection.test.ts +394 -0
  77. package/test/core/collection/failed-ranges.test.ts +270 -0
  78. package/test/core/compose/features.test.ts +183 -0
  79. package/test/core/layout/layout.test.ts +201 -0
  80. package/test/core/list-manager/features/collection.test.ts +704 -0
  81. package/test/core/list-manager/features/viewport.test.ts +698 -0
  82. package/test/core/list-manager/list-manager.test.ts +593 -0
  83. package/test/core/list-manager/utils/calculations.test.ts +433 -0
  84. package/test/core/list-manager/utils/range-calculator.test.ts +569 -0
  85. package/test/core/list-manager/utils/speed-tracker.test.ts +530 -0
  86. package/test/utils/dom-helpers.ts +275 -0
  87. package/test/utils/performance-helpers.ts +392 -0
  88. package/tsconfig.build.json +14 -0
  89. package/tsconfig.json +20 -0
  90. package/dist/index.d.ts +0 -5
  91. package/dist/index.js +0 -38
  92. package/dist/index.mjs +0 -8
@@ -0,0 +1,275 @@
1
+ // test/utils/dom-helpers.ts - DOM Testing Utilities
2
+
3
+ /**
4
+ * Creates a test container element with scrolling capabilities
5
+ * @param height - Height of the container (default: 400px)
6
+ * @param width - Width of the container (default: 100%)
7
+ * @returns HTMLElement configured for testing
8
+ */
9
+ export function createContainer(height = "400px", width = "100%"): HTMLElement {
10
+ const container = document.createElement("div");
11
+ container.style.height = height;
12
+ container.style.width = width;
13
+ container.style.overflow = "auto";
14
+ container.style.position = "relative";
15
+ container.className = "test-container";
16
+ document.body.appendChild(container);
17
+ return container;
18
+ }
19
+
20
+ /**
21
+ * Cleans up a test container by removing it from DOM
22
+ * @param container - Container to cleanup
23
+ */
24
+ export function cleanupContainer(container: HTMLElement): void {
25
+ if (container && container.parentNode) {
26
+ container.parentNode.removeChild(container);
27
+ }
28
+ }
29
+
30
+ /**
31
+ * Simulates a scroll event on an element
32
+ * @param element - Element to scroll
33
+ * @param scrollTop - Scroll position
34
+ * @param scrollLeft - Horizontal scroll position (optional)
35
+ */
36
+ export function simulateScroll(
37
+ element: HTMLElement,
38
+ scrollTop: number,
39
+ scrollLeft: number = 0
40
+ ): void {
41
+ element.scrollTop = scrollTop;
42
+ element.scrollLeft = scrollLeft;
43
+
44
+ const scrollEvent = new Event("scroll", {
45
+ bubbles: true,
46
+ cancelable: true,
47
+ });
48
+
49
+ element.dispatchEvent(scrollEvent);
50
+ }
51
+
52
+ /**
53
+ * Simulates a resize event on an element
54
+ * @param element - Element to resize
55
+ * @param width - New width
56
+ * @param height - New height
57
+ */
58
+ export function simulateResize(
59
+ element: HTMLElement,
60
+ width: number,
61
+ height: number
62
+ ): void {
63
+ element.style.width = `${width}px`;
64
+ element.style.height = `${height}px`;
65
+
66
+ const resizeEvent = new Event("resize", {
67
+ bubbles: true,
68
+ cancelable: true,
69
+ });
70
+
71
+ window.dispatchEvent(resizeEvent);
72
+ }
73
+
74
+ /**
75
+ * Waits for the next animation frame
76
+ * @returns Promise that resolves after requestAnimationFrame
77
+ */
78
+ export function waitForAnimationFrame(): Promise<void> {
79
+ return new Promise((resolve) => {
80
+ requestAnimationFrame(() => resolve());
81
+ });
82
+ }
83
+
84
+ /**
85
+ * Waits for multiple animation frames
86
+ * @param count - Number of frames to wait
87
+ * @returns Promise that resolves after the specified frames
88
+ */
89
+ export function waitForAnimationFrames(count: number): Promise<void> {
90
+ return new Promise((resolve) => {
91
+ let remaining = count;
92
+
93
+ function frame() {
94
+ remaining--;
95
+ if (remaining <= 0) {
96
+ resolve();
97
+ } else {
98
+ requestAnimationFrame(frame);
99
+ }
100
+ }
101
+
102
+ requestAnimationFrame(frame);
103
+ });
104
+ }
105
+
106
+ /**
107
+ * Waits for a specific amount of time
108
+ * @param ms - Milliseconds to wait
109
+ * @returns Promise that resolves after the timeout
110
+ */
111
+ export function waitFor(ms: number): Promise<void> {
112
+ return new Promise((resolve) => setTimeout(resolve, ms));
113
+ }
114
+
115
+ /**
116
+ * Gets the computed style of an element
117
+ * @param element - Element to get style for
118
+ * @param property - CSS property to get
119
+ * @returns The computed style value
120
+ */
121
+ export function getComputedStyleValue(
122
+ element: HTMLElement,
123
+ property: string
124
+ ): string {
125
+ return window.getComputedStyle(element).getPropertyValue(property);
126
+ }
127
+
128
+ /**
129
+ * Checks if an element is visible in the viewport
130
+ * @param element - Element to check
131
+ * @param container - Container element (default: document.body)
132
+ * @returns Whether the element is visible
133
+ */
134
+ export function isElementVisible(
135
+ element: HTMLElement,
136
+ container: HTMLElement = document.body
137
+ ): boolean {
138
+ const rect = element.getBoundingClientRect();
139
+ const containerRect = container.getBoundingClientRect();
140
+
141
+ return (
142
+ rect.top >= containerRect.top &&
143
+ rect.left >= containerRect.left &&
144
+ rect.bottom <= containerRect.bottom &&
145
+ rect.right <= containerRect.right
146
+ );
147
+ }
148
+
149
+ /**
150
+ * Gets all elements within a visible range
151
+ * @param container - Container element
152
+ * @param selector - CSS selector for elements
153
+ * @returns Array of visible elements
154
+ */
155
+ export function getVisibleElements(
156
+ container: HTMLElement,
157
+ selector: string = ".test-item"
158
+ ): HTMLElement[] {
159
+ const elements = Array.from(
160
+ container.querySelectorAll(selector)
161
+ ) as HTMLElement[];
162
+ return elements.filter((el) => isElementVisible(el, container));
163
+ }
164
+
165
+ /**
166
+ * Simulates a mouse event on an element
167
+ * @param element - Target element
168
+ * @param type - Event type (click, mousedown, etc.)
169
+ * @param options - Event options
170
+ */
171
+ export function simulateMouseEvent(
172
+ element: HTMLElement,
173
+ type: string,
174
+ options: Partial<MouseEventInit> = {}
175
+ ): void {
176
+ const event = new MouseEvent(type, {
177
+ bubbles: true,
178
+ cancelable: true,
179
+ ...options,
180
+ });
181
+
182
+ element.dispatchEvent(event);
183
+ }
184
+
185
+ /**
186
+ * Simulates a touch event on an element
187
+ * @param element - Target element
188
+ * @param type - Event type (touchstart, touchmove, etc.)
189
+ * @param touches - Touch points
190
+ */
191
+ export function simulateTouchEvent(
192
+ element: HTMLElement,
193
+ type: string,
194
+ touches: Touch[] = []
195
+ ): void {
196
+ const event = new TouchEvent(type, {
197
+ bubbles: true,
198
+ cancelable: true,
199
+ touches,
200
+ });
201
+
202
+ element.dispatchEvent(event);
203
+ }
204
+
205
+ /**
206
+ * Creates a mock IntersectionObserver for testing
207
+ * @param callback - Callback function
208
+ * @returns Mock IntersectionObserver
209
+ */
210
+ export function createMockIntersectionObserver(
211
+ callback: IntersectionObserverCallback
212
+ ): any {
213
+ const observer = {
214
+ observe: () => {},
215
+ unobserve: () => {},
216
+ disconnect: () => {},
217
+ root: null,
218
+ rootMargin: "",
219
+ thresholds: [],
220
+ takeRecords: () => [],
221
+ };
222
+
223
+ // Store callback for manual triggering
224
+ (observer as any).callback = callback;
225
+
226
+ return observer;
227
+ }
228
+
229
+ /**
230
+ * Triggers intersection observer callback manually
231
+ * @param observer - Mock observer
232
+ * @param entries - Intersection entries
233
+ */
234
+ export function triggerIntersectionObserver(
235
+ observer: any,
236
+ entries: IntersectionObserverEntry[]
237
+ ): void {
238
+ if (observer.callback) {
239
+ observer.callback(entries, observer);
240
+ }
241
+ }
242
+
243
+ /**
244
+ * Creates a mock ResizeObserver for testing
245
+ * @param callback - Callback function
246
+ * @returns Mock ResizeObserver
247
+ */
248
+ export function createMockResizeObserver(
249
+ callback: ResizeObserverCallback
250
+ ): any {
251
+ const observer = {
252
+ observe: () => {},
253
+ unobserve: () => {},
254
+ disconnect: () => {},
255
+ };
256
+
257
+ // Store callback for manual triggering
258
+ (observer as any).callback = callback;
259
+
260
+ return observer;
261
+ }
262
+
263
+ /**
264
+ * Triggers resize observer callback manually
265
+ * @param observer - Mock observer
266
+ * @param entries - Resize entries
267
+ */
268
+ export function triggerResizeObserver(
269
+ observer: any,
270
+ entries: ResizeObserverEntry[]
271
+ ): void {
272
+ if (observer.callback) {
273
+ observer.callback(entries, observer);
274
+ }
275
+ }
@@ -0,0 +1,392 @@
1
+ // test/utils/performance-helpers.ts - Performance Testing Utilities
2
+
3
+ /**
4
+ * Measures the execution time of a function
5
+ * @param callback - Function to measure
6
+ * @returns Promise that resolves with the execution time in milliseconds
7
+ */
8
+ export function measureExecutionTime(
9
+ callback: () => Promise<void> | void
10
+ ): Promise<number> {
11
+ return new Promise(async (resolve) => {
12
+ const start = performance.now();
13
+ await callback();
14
+ const end = performance.now();
15
+ resolve(end - start);
16
+ });
17
+ }
18
+
19
+ /**
20
+ * Measures the time it takes to render content
21
+ * @param callback - Render function
22
+ * @returns Promise that resolves with render time in milliseconds
23
+ */
24
+ export function measureRenderTime(
25
+ callback: () => Promise<void> | void
26
+ ): Promise<number> {
27
+ return measureExecutionTime(callback);
28
+ }
29
+
30
+ /**
31
+ * Creates a large dataset for performance testing
32
+ * @param count - Number of items to create
33
+ * @param template - Template function for creating items
34
+ * @returns Array of test items
35
+ */
36
+ export function createLargeDataset<T>(
37
+ count: number = 10000,
38
+ template: (index: number) => T = (i) =>
39
+ ({
40
+ id: i.toString(),
41
+ name: `Item ${i}`,
42
+ value: Math.random() * 1000,
43
+ } as T)
44
+ ): T[] {
45
+ return Array.from({ length: count }, (_, i) => template(i));
46
+ }
47
+
48
+ /**
49
+ * Creates test items with varying sizes for dynamic height testing
50
+ * @param count - Number of items to create
51
+ * @returns Array of items with different content lengths
52
+ */
53
+ export function createVariableSizeDataset(count: number = 1000) {
54
+ return Array.from({ length: count }, (_, i) => ({
55
+ id: i.toString(),
56
+ name: `Item ${i}`,
57
+ description: "Lorem ipsum ".repeat(Math.floor(Math.random() * 10) + 1),
58
+ tags: Array.from(
59
+ { length: Math.floor(Math.random() * 5) + 1 },
60
+ (_, j) => `tag${j}`
61
+ ),
62
+ }));
63
+ }
64
+
65
+ /**
66
+ * Measures frame rate during a series of operations
67
+ * @param operations - Array of operations to perform
68
+ * @param duration - Duration to measure in milliseconds
69
+ * @returns Promise that resolves with average FPS
70
+ */
71
+ export function measureFrameRate(
72
+ operations: (() => void)[],
73
+ duration: number = 1000
74
+ ): Promise<number> {
75
+ return new Promise((resolve) => {
76
+ let frameCount = 0;
77
+ let lastTime = performance.now();
78
+ const endTime = lastTime + duration;
79
+ let operationIndex = 0;
80
+
81
+ function frame() {
82
+ const currentTime = performance.now();
83
+
84
+ if (currentTime >= endTime) {
85
+ const fps = (frameCount / duration) * 1000;
86
+ resolve(fps);
87
+ return;
88
+ }
89
+
90
+ // Perform operation
91
+ if (operations.length > 0) {
92
+ operations[operationIndex % operations.length]();
93
+ operationIndex++;
94
+ }
95
+
96
+ frameCount++;
97
+ requestAnimationFrame(frame);
98
+ }
99
+
100
+ requestAnimationFrame(frame);
101
+ });
102
+ }
103
+
104
+ /**
105
+ * Measures scroll performance by simulating rapid scrolling
106
+ * @param container - Container element to scroll
107
+ * @param scrollDistance - Total distance to scroll
108
+ * @param scrollSteps - Number of scroll steps
109
+ * @returns Promise that resolves with performance metrics
110
+ */
111
+ export function measureScrollPerformance(
112
+ container: HTMLElement,
113
+ scrollDistance: number = 10000,
114
+ scrollSteps: number = 100
115
+ ): Promise<{
116
+ averageFrameTime: number;
117
+ maxFrameTime: number;
118
+ minFrameTime: number;
119
+ droppedFrames: number;
120
+ }> {
121
+ return new Promise((resolve) => {
122
+ const frameTimes: number[] = [];
123
+ const stepSize = scrollDistance / scrollSteps;
124
+ let currentStep = 0;
125
+ let lastTime = performance.now();
126
+ const targetFrameTime = 16.67; // 60fps = 16.67ms per frame
127
+
128
+ function scrollStep() {
129
+ const currentTime = performance.now();
130
+ const frameTime = currentTime - lastTime;
131
+ frameTimes.push(frameTime);
132
+
133
+ if (currentStep >= scrollSteps) {
134
+ const averageFrameTime =
135
+ frameTimes.reduce((a, b) => a + b, 0) / frameTimes.length;
136
+ const maxFrameTime = Math.max(...frameTimes);
137
+ const minFrameTime = Math.min(...frameTimes);
138
+ const droppedFrames = frameTimes.filter(
139
+ (time) => time > targetFrameTime
140
+ ).length;
141
+
142
+ resolve({
143
+ averageFrameTime,
144
+ maxFrameTime,
145
+ minFrameTime,
146
+ droppedFrames,
147
+ });
148
+ return;
149
+ }
150
+
151
+ // Perform scroll
152
+ container.scrollTop = currentStep * stepSize;
153
+ const scrollEvent = new Event("scroll", { bubbles: true });
154
+ container.dispatchEvent(scrollEvent);
155
+
156
+ currentStep++;
157
+ lastTime = currentTime;
158
+ requestAnimationFrame(scrollStep);
159
+ }
160
+
161
+ requestAnimationFrame(scrollStep);
162
+ });
163
+ }
164
+
165
+ /**
166
+ * Measures memory usage (approximate)
167
+ * @returns Memory usage information
168
+ */
169
+ export function measureMemoryUsage(): {
170
+ heapUsed: number;
171
+ heapTotal: number;
172
+ external: number;
173
+ } {
174
+ // For browser environment, we can't access precise memory info
175
+ // This is a placeholder that would work in Node.js
176
+ if (typeof process !== "undefined" && process.memoryUsage) {
177
+ const usage = process.memoryUsage();
178
+ return {
179
+ heapUsed: usage.heapUsed,
180
+ heapTotal: usage.heapTotal,
181
+ external: usage.external,
182
+ };
183
+ }
184
+
185
+ // Browser fallback - approximate values
186
+ return {
187
+ heapUsed: 0,
188
+ heapTotal: 0,
189
+ external: 0,
190
+ };
191
+ }
192
+
193
+ /**
194
+ * Measures DOM manipulation performance
195
+ * @param manipulationFn - Function that performs DOM manipulation
196
+ * @param iterations - Number of iterations to perform
197
+ * @returns Promise that resolves with performance metrics
198
+ */
199
+ export function measureDOMPerformance(
200
+ manipulationFn: () => void,
201
+ iterations: number = 1000
202
+ ): Promise<{
203
+ totalTime: number;
204
+ averageTime: number;
205
+ operationsPerSecond: number;
206
+ }> {
207
+ return new Promise((resolve) => {
208
+ const start = performance.now();
209
+
210
+ for (let i = 0; i < iterations; i++) {
211
+ manipulationFn();
212
+ }
213
+
214
+ const end = performance.now();
215
+ const totalTime = end - start;
216
+ const averageTime = totalTime / iterations;
217
+ const operationsPerSecond = (iterations / totalTime) * 1000;
218
+
219
+ resolve({
220
+ totalTime,
221
+ averageTime,
222
+ operationsPerSecond,
223
+ });
224
+ });
225
+ }
226
+
227
+ /**
228
+ * Runs a performance benchmark and compares against baseline
229
+ * @param name - Name of the benchmark
230
+ * @param fn - Function to benchmark
231
+ * @param baseline - Baseline time in milliseconds
232
+ * @returns Promise that resolves with benchmark results
233
+ */
234
+ export function runBenchmark(
235
+ name: string,
236
+ fn: () => Promise<void> | void,
237
+ baseline?: number
238
+ ): Promise<{
239
+ name: string;
240
+ time: number;
241
+ baseline?: number;
242
+ ratio?: number;
243
+ passed: boolean;
244
+ }> {
245
+ return new Promise(async (resolve) => {
246
+ const time = await measureExecutionTime(fn);
247
+ const result = {
248
+ name,
249
+ time,
250
+ baseline,
251
+ ratio: baseline ? time / baseline : undefined,
252
+ passed: baseline ? time <= baseline : true,
253
+ };
254
+
255
+ resolve(result);
256
+ });
257
+ }
258
+
259
+ /**
260
+ * Stress tests a function with increasing load
261
+ * @param fn - Function to stress test
262
+ * @param startLoad - Starting load (e.g., number of items)
263
+ * @param maxLoad - Maximum load to test
264
+ * @param stepSize - Step size for increasing load
265
+ * @returns Promise that resolves with stress test results
266
+ */
267
+ export function stressTest(
268
+ fn: (load: number) => Promise<void> | void,
269
+ startLoad: number = 100,
270
+ maxLoad: number = 10000,
271
+ stepSize: number = 100
272
+ ): Promise<
273
+ {
274
+ load: number;
275
+ time: number;
276
+ success: boolean;
277
+ }[]
278
+ > {
279
+ return new Promise(async (resolve) => {
280
+ const results: { load: number; time: number; success: boolean }[] = [];
281
+
282
+ for (let load = startLoad; load <= maxLoad; load += stepSize) {
283
+ try {
284
+ const time = await measureExecutionTime(() => fn(load));
285
+ results.push({ load, time, success: true });
286
+ } catch (error) {
287
+ results.push({ load, time: -1, success: false });
288
+ break; // Stop on first failure
289
+ }
290
+ }
291
+
292
+ resolve(results);
293
+ });
294
+ }
295
+
296
+ /**
297
+ * Measures the performance of virtual scrolling
298
+ * @param container - Container element
299
+ * @param itemCount - Total number of items
300
+ * @param visibleItems - Number of visible items
301
+ * @param scrollTests - Number of scroll positions to test
302
+ * @returns Promise that resolves with virtual scroll performance metrics
303
+ */
304
+ export function measureVirtualScrollPerformance(
305
+ container: HTMLElement,
306
+ itemCount: number = 10000,
307
+ visibleItems: number = 20,
308
+ scrollTests: number = 100
309
+ ): Promise<{
310
+ renderTime: number;
311
+ scrollTime: number;
312
+ memoryEfficiency: number;
313
+ }> {
314
+ return new Promise(async (resolve) => {
315
+ // Measure initial render time
316
+ const renderTime = await measureRenderTime(async () => {
317
+ // This would be the virtual scroll render function
318
+ // Placeholder for now
319
+ await new Promise((resolve) => setTimeout(resolve, 1));
320
+ });
321
+
322
+ // Measure scroll performance
323
+ const scrollTime = await measureScrollPerformance(
324
+ container,
325
+ 5000,
326
+ scrollTests
327
+ );
328
+
329
+ // Calculate memory efficiency (visible items / total items)
330
+ const memoryEfficiency = visibleItems / itemCount;
331
+
332
+ resolve({
333
+ renderTime,
334
+ scrollTime: scrollTime.averageFrameTime,
335
+ memoryEfficiency,
336
+ });
337
+ });
338
+ }
339
+
340
+ /**
341
+ * Creates a performance test suite
342
+ * @param tests - Array of test configurations
343
+ * @returns Promise that resolves with all test results
344
+ */
345
+ export function runPerformanceTestSuite(
346
+ tests: {
347
+ name: string;
348
+ fn: () => Promise<void> | void;
349
+ baseline?: number;
350
+ timeout?: number;
351
+ }[]
352
+ ): Promise<
353
+ {
354
+ name: string;
355
+ time: number;
356
+ baseline?: number;
357
+ passed: boolean;
358
+ error?: string;
359
+ }[]
360
+ > {
361
+ return new Promise(async (resolve) => {
362
+ const results: {
363
+ name: string;
364
+ time: number;
365
+ baseline?: number;
366
+ passed: boolean;
367
+ error?: string;
368
+ }[] = [];
369
+
370
+ for (const test of tests) {
371
+ try {
372
+ const benchmark = await runBenchmark(test.name, test.fn, test.baseline);
373
+ results.push({
374
+ name: benchmark.name,
375
+ time: benchmark.time,
376
+ baseline: benchmark.baseline,
377
+ passed: benchmark.passed,
378
+ });
379
+ } catch (error) {
380
+ results.push({
381
+ name: test.name,
382
+ time: -1,
383
+ baseline: test.baseline,
384
+ passed: false,
385
+ error: error instanceof Error ? error.message : String(error),
386
+ });
387
+ }
388
+ }
389
+
390
+ resolve(results);
391
+ });
392
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "declaration": true,
5
+ "emitDeclarationOnly": true,
6
+ "outDir": "dist",
7
+ "rootDir": "src",
8
+ "skipLibCheck": true,
9
+ "noEmitOnError": false,
10
+ "typeRoots": ["./node_modules/@types", "./src/types"]
11
+ },
12
+ "include": ["src/**/*.ts", "src/types/**/*.d.ts"],
13
+ "exclude": ["node_modules", "dist", "**/*.test.ts", "test/**/*"]
14
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ESNext",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "esModuleInterop": true,
7
+ "strict": true,
8
+ "skipLibCheck": true,
9
+ "outDir": "dist",
10
+ "rootDir": "src",
11
+ "declaration": true,
12
+ "lib": ["ESNext", "DOM"],
13
+ "types": ["bun-types"],
14
+ "paths": {
15
+ "@/*": ["./src/*"]
16
+ }
17
+ },
18
+ "include": ["src/**/*.ts"],
19
+ "exclude": ["node_modules", "dist", "**/*.test.ts"]
20
+ }
package/dist/index.d.ts DELETED
@@ -1,5 +0,0 @@
1
- /**
2
- * mtrl-addons
3
- * Additional components and utilities for the mtrl system
4
- */
5
- export declare const version = "0.1.0";