mintwaterfall 0.8.6

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 (38) hide show
  1. package/CHANGELOG.md +223 -0
  2. package/CONTRIBUTING.md +199 -0
  3. package/README.md +363 -0
  4. package/dist/index.d.ts +149 -0
  5. package/dist/mintwaterfall.cjs.js +7978 -0
  6. package/dist/mintwaterfall.esm.js +7907 -0
  7. package/dist/mintwaterfall.min.js +7 -0
  8. package/dist/mintwaterfall.umd.js +7978 -0
  9. package/index.d.ts +149 -0
  10. package/package.json +126 -0
  11. package/src/enterprise/enterprise-core.js +0 -0
  12. package/src/enterprise/enterprise-feature-template.js +0 -0
  13. package/src/enterprise/feature-registry.js +0 -0
  14. package/src/enterprise/features/breakdown.js +0 -0
  15. package/src/features/breakdown.js +0 -0
  16. package/src/features/conditional-formatting.js +0 -0
  17. package/src/index.js +111 -0
  18. package/src/mintwaterfall-accessibility.ts +680 -0
  19. package/src/mintwaterfall-advanced-data.ts +1034 -0
  20. package/src/mintwaterfall-advanced-interactions.ts +649 -0
  21. package/src/mintwaterfall-advanced-performance.ts +582 -0
  22. package/src/mintwaterfall-animations.ts +595 -0
  23. package/src/mintwaterfall-brush.ts +471 -0
  24. package/src/mintwaterfall-chart-core.ts +296 -0
  25. package/src/mintwaterfall-chart.ts +1915 -0
  26. package/src/mintwaterfall-data.ts +1100 -0
  27. package/src/mintwaterfall-export.ts +475 -0
  28. package/src/mintwaterfall-hierarchical-layouts.ts +724 -0
  29. package/src/mintwaterfall-layouts.ts +647 -0
  30. package/src/mintwaterfall-performance.ts +573 -0
  31. package/src/mintwaterfall-scales.ts +437 -0
  32. package/src/mintwaterfall-shapes.ts +385 -0
  33. package/src/mintwaterfall-statistics.ts +821 -0
  34. package/src/mintwaterfall-themes.ts +391 -0
  35. package/src/mintwaterfall-tooltip.ts +450 -0
  36. package/src/mintwaterfall-zoom.ts +399 -0
  37. package/src/types/js-modules.d.ts +25 -0
  38. package/src/utils/compatibility-layer.js +0 -0
@@ -0,0 +1,573 @@
1
+ // MintWaterfall Performance System - TypeScript Version
2
+ // Implements virtualization, incremental updates, and memory optimization with full type safety
3
+
4
+ import * as d3 from 'd3';
5
+
6
+ // Type definitions for performance system
7
+ export interface PerformanceMetrics {
8
+ renderTime: number;
9
+ dataProcessingTime: number;
10
+ memoryUsage: number;
11
+ visibleElements: number;
12
+ totalElements: number;
13
+ fps: number;
14
+ lastFrameTime: number;
15
+ averageFrameTime: number;
16
+ peakMemoryUsage: number;
17
+ renderCalls: number;
18
+ }
19
+
20
+ export interface VirtualizationConfig {
21
+ enabled: boolean;
22
+ chunkSize: number;
23
+ renderThreshold: number;
24
+ bufferSize: number;
25
+ preloadCount: number;
26
+ recycleNodes: boolean;
27
+ }
28
+
29
+ export interface VirtualViewport {
30
+ start: number;
31
+ end: number;
32
+ visible: number[];
33
+ bufferStart: number;
34
+ bufferEnd: number;
35
+ }
36
+
37
+ export interface PerformanceOptimization {
38
+ debouncing: boolean;
39
+ throttling: boolean;
40
+ batchUpdates: boolean;
41
+ memoryPooling: boolean;
42
+ geometryOptimization: boolean;
43
+ cssOptimization: boolean;
44
+ }
45
+
46
+ export interface MemoryPool {
47
+ elements: Map<string, any[]>;
48
+ maxSize: number;
49
+ currentSize: number;
50
+ hitCount: number;
51
+ missCount: number;
52
+ }
53
+
54
+ export interface RenderBatch {
55
+ operations: RenderOperation[];
56
+ priority: number;
57
+ timestamp: number;
58
+ elementCount: number;
59
+ }
60
+
61
+ export interface RenderOperation {
62
+ type: 'create' | 'update' | 'remove' | 'style' | 'attribute';
63
+ element: any;
64
+ data: any;
65
+ properties: Record<string, any>;
66
+ }
67
+
68
+ export interface PerformanceProfiler {
69
+ startTime: number;
70
+ endTime: number;
71
+ samples: number[];
72
+ averageTime: number;
73
+ minTime: number;
74
+ maxTime: number;
75
+ }
76
+
77
+ export interface PerformanceManager {
78
+ enableVirtualization(options?: Partial<VirtualizationConfig>): PerformanceManager;
79
+ disableVirtualization(): PerformanceManager;
80
+ optimizeRendering(container: d3.Selection<d3.BaseType, any, any, any>, data: any[]): PerformanceManager;
81
+ profileOperation(name: string, operation: () => any): any;
82
+ getMetrics(): PerformanceMetrics;
83
+ resetMetrics(): PerformanceManager;
84
+ enableMemoryPooling(options?: Partial<MemoryPool>): PerformanceManager;
85
+ createRenderBatch(): RenderBatch;
86
+ flushRenderBatch(batch: RenderBatch): PerformanceManager;
87
+ setUpdateStrategy(strategy: 'immediate' | 'debounced' | 'throttled' | 'batched'): PerformanceManager;
88
+ getDashboard(): HTMLElement | null;
89
+ enableDashboard(container?: HTMLElement): PerformanceManager;
90
+ disableDashboard(): PerformanceManager;
91
+ optimizeMemory(): PerformanceManager;
92
+ getRecommendations(): string[];
93
+ }
94
+
95
+ export function createPerformanceManager(): PerformanceManager {
96
+
97
+ // Performance metrics tracking
98
+ let performanceMetrics: PerformanceMetrics = {
99
+ renderTime: 0,
100
+ dataProcessingTime: 0,
101
+ memoryUsage: 0,
102
+ visibleElements: 0,
103
+ totalElements: 0,
104
+ fps: 0,
105
+ lastFrameTime: 0,
106
+ averageFrameTime: 0,
107
+ peakMemoryUsage: 0,
108
+ renderCalls: 0
109
+ };
110
+
111
+ // Virtualization configuration
112
+ let virtualizationConfig: VirtualizationConfig = {
113
+ enabled: false,
114
+ chunkSize: 1000,
115
+ renderThreshold: 10000,
116
+ bufferSize: 200,
117
+ preloadCount: 3,
118
+ recycleNodes: true
119
+ };
120
+
121
+ let virtualViewport: VirtualViewport = {
122
+ start: 0,
123
+ end: 100,
124
+ visible: [],
125
+ bufferStart: 0,
126
+ bufferEnd: 100
127
+ };
128
+
129
+ // Performance optimization settings
130
+ let optimizationConfig: PerformanceOptimization = {
131
+ debouncing: true,
132
+ throttling: true,
133
+ batchUpdates: true,
134
+ memoryPooling: true,
135
+ geometryOptimization: true,
136
+ cssOptimization: true
137
+ };
138
+
139
+ // Memory pool for reusing DOM elements
140
+ let memoryPool: MemoryPool = {
141
+ elements: new Map(),
142
+ maxSize: 1000,
143
+ currentSize: 0,
144
+ hitCount: 0,
145
+ missCount: 0
146
+ };
147
+
148
+ // Render batching system
149
+ let currentBatch: RenderBatch | null = null;
150
+ let batchTimeout: number | null = null;
151
+ let updateStrategy: 'immediate' | 'debounced' | 'throttled' | 'batched' = 'immediate';
152
+
153
+ // Performance profiling
154
+ let profilers = new Map<string, PerformanceProfiler>();
155
+ let dashboardElement: HTMLElement | null = null;
156
+
157
+ // Frame rate tracking
158
+ let frameCount = 0;
159
+ let lastFpsTime = performance.now();
160
+
161
+ function enableVirtualization(options: Partial<VirtualizationConfig> = {}): PerformanceManager {
162
+ Object.assign(virtualizationConfig, options);
163
+ virtualizationConfig.enabled = true;
164
+
165
+ console.log('MintWaterfall: Virtualization enabled with config:', virtualizationConfig);
166
+ return performanceManager;
167
+ }
168
+
169
+ function disableVirtualization(): PerformanceManager {
170
+ virtualizationConfig.enabled = false;
171
+ console.log('MintWaterfall: Virtualization disabled');
172
+ return performanceManager;
173
+ }
174
+
175
+ function calculateVisibleRange(scrollTop: number, containerHeight: number, itemHeight: number): [number, number] {
176
+ const start = Math.floor(scrollTop / itemHeight);
177
+ const visibleCount = Math.ceil(containerHeight / itemHeight);
178
+ const end = start + visibleCount;
179
+
180
+ // Add buffer for smooth scrolling
181
+ const bufferStart = Math.max(0, start - virtualizationConfig.bufferSize);
182
+ const bufferEnd = end + virtualizationConfig.bufferSize;
183
+
184
+ return [bufferStart, bufferEnd];
185
+ }
186
+
187
+ function optimizeRendering(container: d3.Selection<d3.BaseType, any, any, any>, data: any[]): PerformanceManager {
188
+ const startTime = performance.now();
189
+
190
+ performanceMetrics.totalElements = data.length;
191
+
192
+ if (virtualizationConfig.enabled && data.length > virtualizationConfig.renderThreshold) {
193
+ renderVirtualized(container, data);
194
+ } else {
195
+ renderDirect(container, data);
196
+ }
197
+
198
+ const endTime = performance.now();
199
+ performanceMetrics.renderTime = endTime - startTime;
200
+ performanceMetrics.renderCalls++;
201
+
202
+ updateFPS();
203
+ return performanceManager;
204
+ }
205
+
206
+ function renderVirtualized(container: d3.Selection<d3.BaseType, any, any, any>, data: any[]): void {
207
+ // Implement virtualization logic
208
+ const containerNode = container.node() as Element;
209
+ if (!containerNode) return;
210
+
211
+ const containerHeight = containerNode.clientHeight;
212
+ const scrollTop = (containerNode as HTMLElement).scrollTop || 0;
213
+ const itemHeight = 30; // Estimate or calculate from data
214
+
215
+ const [visibleStart, visibleEnd] = calculateVisibleRange(scrollTop, containerHeight, itemHeight);
216
+ const visibleData = data.slice(visibleStart, Math.min(visibleEnd, data.length));
217
+
218
+ virtualViewport.start = visibleStart;
219
+ virtualViewport.end = visibleEnd;
220
+ virtualViewport.visible = visibleData.map((_, i) => i + visibleStart);
221
+
222
+ performanceMetrics.visibleElements = visibleData.length;
223
+
224
+ // Render only visible elements with proper typing
225
+ const elements = container.selectAll<SVGGElement, any>('.virtual-item')
226
+ .data(visibleData, (d: any, i: number) => `item-${i + visibleStart}`);
227
+
228
+ elements.exit().remove();
229
+
230
+ const enter = elements.enter().append<SVGGElement>('g')
231
+ .attr('class', 'virtual-item');
232
+
233
+ const merged = elements.merge(enter);
234
+ merged.attr('transform', (d: any, i: number) => `translate(0, ${(i + visibleStart) * itemHeight})`);
235
+ }
236
+
237
+ function renderDirect(container: d3.Selection<d3.BaseType, any, any, any>, data: any[]): void {
238
+ // Standard rendering for smaller datasets
239
+ performanceMetrics.visibleElements = data.length;
240
+
241
+ const elements = container.selectAll<SVGGElement, any>('.chart-element')
242
+ .data(data);
243
+
244
+ elements.exit().remove();
245
+
246
+ const enter = elements.enter().append<SVGGElement>('g')
247
+ .attr('class', 'chart-element');
248
+
249
+ const merged = elements.merge(enter);
250
+ // Apply transformations and styles here - merged variable prevents compilation errors
251
+ }
252
+
253
+ function profileOperation(name: string, operation: () => any): any {
254
+ const startTime = performance.now();
255
+ const result = operation();
256
+ const endTime = performance.now();
257
+ const duration = endTime - startTime;
258
+
259
+ if (!profilers.has(name)) {
260
+ profilers.set(name, {
261
+ startTime: 0,
262
+ endTime: 0,
263
+ samples: [],
264
+ averageTime: 0,
265
+ minTime: Infinity,
266
+ maxTime: 0
267
+ });
268
+ }
269
+
270
+ const profiler = profilers.get(name)!;
271
+ profiler.samples.push(duration);
272
+ profiler.minTime = Math.min(profiler.minTime, duration);
273
+ profiler.maxTime = Math.max(profiler.maxTime, duration);
274
+ profiler.averageTime = profiler.samples.reduce((a, b) => a + b, 0) / profiler.samples.length;
275
+
276
+ // Keep only recent samples for rolling average
277
+ if (profiler.samples.length > 100) {
278
+ profiler.samples.shift();
279
+ }
280
+
281
+ return result;
282
+ }
283
+
284
+ function getMetrics(): PerformanceMetrics {
285
+ // Update memory usage if available
286
+ if ('memory' in performance) {
287
+ const memInfo = (performance as any).memory;
288
+ performanceMetrics.memoryUsage = memInfo.usedJSHeapSize;
289
+ performanceMetrics.peakMemoryUsage = Math.max(performanceMetrics.peakMemoryUsage, memInfo.usedJSHeapSize);
290
+ }
291
+
292
+ return { ...performanceMetrics };
293
+ }
294
+
295
+ function resetMetrics(): PerformanceManager {
296
+ performanceMetrics = {
297
+ renderTime: 0,
298
+ dataProcessingTime: 0,
299
+ memoryUsage: 0,
300
+ visibleElements: 0,
301
+ totalElements: 0,
302
+ fps: 0,
303
+ lastFrameTime: 0,
304
+ averageFrameTime: 0,
305
+ peakMemoryUsage: 0,
306
+ renderCalls: 0
307
+ };
308
+
309
+ profilers.clear();
310
+ frameCount = 0;
311
+ lastFpsTime = performance.now();
312
+
313
+ return performanceManager;
314
+ }
315
+
316
+ function enableMemoryPooling(options: Partial<MemoryPool> = {}): PerformanceManager {
317
+ Object.assign(memoryPool, options);
318
+ optimizationConfig.memoryPooling = true;
319
+
320
+ console.log('MintWaterfall: Memory pooling enabled');
321
+ return performanceManager;
322
+ }
323
+
324
+ function getFromPool(type: string): any {
325
+ if (!optimizationConfig.memoryPooling) return null;
326
+
327
+ const pool = memoryPool.elements.get(type);
328
+ if (pool && pool.length > 0) {
329
+ memoryPool.hitCount++;
330
+ memoryPool.currentSize--;
331
+ return pool.pop();
332
+ }
333
+
334
+ memoryPool.missCount++;
335
+ return null;
336
+ }
337
+
338
+ function returnToPool(type: string, element: any): void {
339
+ if (!optimizationConfig.memoryPooling || memoryPool.currentSize >= memoryPool.maxSize) return;
340
+
341
+ if (!memoryPool.elements.has(type)) {
342
+ memoryPool.elements.set(type, []);
343
+ }
344
+
345
+ const pool = memoryPool.elements.get(type)!;
346
+ pool.push(element);
347
+ memoryPool.currentSize++;
348
+ }
349
+
350
+ function createRenderBatch(): RenderBatch {
351
+ return {
352
+ operations: [],
353
+ priority: 1,
354
+ timestamp: performance.now(),
355
+ elementCount: 0
356
+ };
357
+ }
358
+
359
+ function flushRenderBatch(batch: RenderBatch): PerformanceManager {
360
+ const startTime = performance.now();
361
+
362
+ // Sort operations by priority and type for optimal rendering
363
+ batch.operations.sort((a, b) => {
364
+ const typeOrder = ['remove', 'create', 'update', 'style', 'attribute'];
365
+ return typeOrder.indexOf(a.type) - typeOrder.indexOf(b.type);
366
+ });
367
+
368
+ // Execute operations in batch
369
+ batch.operations.forEach(operation => {
370
+ executeRenderOperation(operation);
371
+ });
372
+
373
+ const endTime = performance.now();
374
+ performanceMetrics.renderTime += endTime - startTime;
375
+
376
+ return performanceManager;
377
+ }
378
+
379
+ function executeRenderOperation(operation: RenderOperation): void {
380
+ const { type, element, properties } = operation;
381
+
382
+ switch (type) {
383
+ case 'create':
384
+ // Create new element logic
385
+ break;
386
+ case 'update':
387
+ // Update element data logic
388
+ break;
389
+ case 'remove':
390
+ // Remove element logic
391
+ if (element && element.remove) {
392
+ element.remove();
393
+ }
394
+ break;
395
+ case 'style':
396
+ // Apply styles
397
+ if (element && properties) {
398
+ Object.keys(properties).forEach(prop => {
399
+ element.style(prop, properties[prop]);
400
+ });
401
+ }
402
+ break;
403
+ case 'attribute':
404
+ // Apply attributes
405
+ if (element && properties) {
406
+ Object.keys(properties).forEach(prop => {
407
+ element.attr(prop, properties[prop]);
408
+ });
409
+ }
410
+ break;
411
+ }
412
+ }
413
+
414
+ function setUpdateStrategy(strategy: 'immediate' | 'debounced' | 'throttled' | 'batched'): PerformanceManager {
415
+ updateStrategy = strategy;
416
+ console.log(`MintWaterfall: Update strategy set to ${strategy}`);
417
+ return performanceManager;
418
+ }
419
+
420
+ function updateFPS(): void {
421
+ frameCount++;
422
+ const currentTime = performance.now();
423
+
424
+ if (currentTime - lastFpsTime >= 1000) {
425
+ performanceMetrics.fps = Math.round((frameCount * 1000) / (currentTime - lastFpsTime));
426
+ performanceMetrics.averageFrameTime = (currentTime - lastFpsTime) / frameCount;
427
+ frameCount = 0;
428
+ lastFpsTime = currentTime;
429
+ }
430
+
431
+ performanceMetrics.lastFrameTime = currentTime;
432
+ }
433
+
434
+ function createDashboard(): HTMLElement {
435
+ const dashboard = document.createElement('div');
436
+ dashboard.className = 'mintwaterfall-performance-dashboard';
437
+ dashboard.style.cssText = `
438
+ position: fixed;
439
+ top: 10px;
440
+ right: 10px;
441
+ background: rgba(0, 0, 0, 0.8);
442
+ color: white;
443
+ padding: 10px;
444
+ border-radius: 5px;
445
+ font-family: monospace;
446
+ font-size: 12px;
447
+ z-index: 10000;
448
+ max-width: 300px;
449
+ `;
450
+
451
+ return dashboard;
452
+ }
453
+
454
+ function updateDashboard(): void {
455
+ if (!dashboardElement) return;
456
+
457
+ const metrics = getMetrics();
458
+ const memoryMB = (metrics.memoryUsage / 1024 / 1024).toFixed(2);
459
+ const peakMemoryMB = (metrics.peakMemoryUsage / 1024 / 1024).toFixed(2);
460
+
461
+ dashboardElement.innerHTML = `
462
+ <div><strong>MintWaterfall Performance</strong></div>
463
+ <div>FPS: ${metrics.fps}</div>
464
+ <div>Render Time: ${metrics.renderTime.toFixed(2)}ms</div>
465
+ <div>Memory: ${memoryMB}MB (Peak: ${peakMemoryMB}MB)</div>
466
+ <div>Visible Elements: ${metrics.visibleElements}/${metrics.totalElements}</div>
467
+ <div>Render Calls: ${metrics.renderCalls}</div>
468
+ <div>Virtualization: ${virtualizationConfig.enabled ? 'ON' : 'OFF'}</div>
469
+ <div>Pool Hit Rate: ${memoryPool.hitCount + memoryPool.missCount > 0 ?
470
+ ((memoryPool.hitCount / (memoryPool.hitCount + memoryPool.missCount)) * 100).toFixed(1) : 0}%</div>
471
+ `;
472
+ }
473
+
474
+ function enableDashboard(container?: HTMLElement): PerformanceManager {
475
+ if (!dashboardElement) {
476
+ dashboardElement = createDashboard();
477
+ }
478
+
479
+ const targetContainer = container || document.body;
480
+ if (targetContainer && !targetContainer.contains(dashboardElement)) {
481
+ targetContainer.appendChild(dashboardElement);
482
+ }
483
+
484
+ // Update dashboard periodically
485
+ setInterval(updateDashboard, 500);
486
+
487
+ return performanceManager;
488
+ }
489
+
490
+ function disableDashboard(): PerformanceManager {
491
+ if (dashboardElement && dashboardElement.parentNode) {
492
+ dashboardElement.parentNode.removeChild(dashboardElement);
493
+ dashboardElement = null;
494
+ }
495
+ return performanceManager;
496
+ }
497
+
498
+ function getDashboard(): HTMLElement | null {
499
+ return dashboardElement;
500
+ }
501
+
502
+ function optimizeMemory(): PerformanceManager {
503
+ // Force garbage collection if available
504
+ if ((window as any).gc) {
505
+ (window as any).gc();
506
+ }
507
+
508
+ // Clear unused pools
509
+ memoryPool.elements.forEach((pool, type) => {
510
+ if (pool.length > 50) {
511
+ pool.splice(25); // Keep only recent 25 elements
512
+ }
513
+ });
514
+
515
+ // Clear old profiler samples
516
+ profilers.forEach(profiler => {
517
+ if (profiler.samples.length > 50) {
518
+ profiler.samples.splice(0, profiler.samples.length - 50);
519
+ }
520
+ });
521
+
522
+ console.log('MintWaterfall: Memory optimization completed');
523
+ return performanceManager;
524
+ }
525
+
526
+ function getRecommendations(): string[] {
527
+ const recommendations: string[] = [];
528
+ const metrics = getMetrics();
529
+
530
+ if (metrics.totalElements > 5000 && !virtualizationConfig.enabled) {
531
+ recommendations.push('Enable virtualization for improved performance with large datasets');
532
+ }
533
+
534
+ if (metrics.fps < 30) {
535
+ recommendations.push('Consider reducing visual complexity or enabling performance optimizations');
536
+ }
537
+
538
+ if (metrics.memoryUsage > 100 * 1024 * 1024) { // 100MB
539
+ recommendations.push('Memory usage is high - consider enabling memory pooling or reducing data size');
540
+ }
541
+
542
+ if (metrics.renderTime > 100) {
543
+ recommendations.push('Render time is slow - consider batching updates or optimizing render operations');
544
+ }
545
+
546
+ const poolEfficiency = memoryPool.hitCount / (memoryPool.hitCount + memoryPool.missCount || 1);
547
+ if (poolEfficiency < 0.5 && optimizationConfig.memoryPooling) {
548
+ recommendations.push('Memory pool efficiency is low - consider adjusting pool size or strategy');
549
+ }
550
+
551
+ return recommendations;
552
+ }
553
+
554
+ const performanceManager: PerformanceManager = {
555
+ enableVirtualization,
556
+ disableVirtualization,
557
+ optimizeRendering,
558
+ profileOperation,
559
+ getMetrics,
560
+ resetMetrics,
561
+ enableMemoryPooling,
562
+ createRenderBatch,
563
+ flushRenderBatch,
564
+ setUpdateStrategy,
565
+ getDashboard,
566
+ enableDashboard,
567
+ disableDashboard,
568
+ optimizeMemory,
569
+ getRecommendations
570
+ };
571
+
572
+ return performanceManager;
573
+ }