energy-visualization-sankey 1.0.11 → 1.0.13

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 (45) hide show
  1. package/.cursorrules +41 -0
  2. package/README.md +8 -1
  3. package/bun.lock +1426 -0
  4. package/dist/sankey.esm.js +108 -79
  5. package/dist/sankey.esm.js.map +1 -1
  6. package/dist/sankey.umd.js +8720 -8687
  7. package/dist/sankey.umd.js.map +1 -1
  8. package/dist/types/core/Sankey.d.ts +294 -0
  9. package/dist/types/core/Sankey.d.ts.map +1 -0
  10. package/dist/types/core/events/EventBus.d.ts +195 -0
  11. package/dist/types/core/events/EventBus.d.ts.map +1 -0
  12. package/dist/types/core/types/events.d.ts +42 -0
  13. package/dist/types/core/types/events.d.ts.map +1 -0
  14. package/dist/types/index.d.ts +19 -0
  15. package/dist/types/index.d.ts.map +1 -0
  16. package/dist/types/services/AnimationService.d.ts +229 -0
  17. package/dist/types/services/AnimationService.d.ts.map +1 -0
  18. package/dist/types/services/ConfigurationService.d.ts +182 -0
  19. package/dist/types/services/ConfigurationService.d.ts.map +1 -0
  20. package/dist/types/services/InteractionService.d.ts +377 -0
  21. package/dist/types/services/InteractionService.d.ts.map +1 -0
  22. package/dist/types/services/RenderingService.d.ts +160 -0
  23. package/dist/types/services/RenderingService.d.ts.map +1 -0
  24. package/dist/types/services/calculation/GraphService.d.ts +111 -0
  25. package/dist/types/services/calculation/GraphService.d.ts.map +1 -0
  26. package/dist/types/services/calculation/SummaryService.d.ts +149 -0
  27. package/dist/types/services/calculation/SummaryService.d.ts.map +1 -0
  28. package/dist/types/services/data/DataService.d.ts +167 -0
  29. package/dist/types/services/data/DataService.d.ts.map +1 -0
  30. package/dist/types/services/data/DataValidationService.d.ts +48 -0
  31. package/dist/types/services/data/DataValidationService.d.ts.map +1 -0
  32. package/dist/types/types/index.d.ts +194 -0
  33. package/dist/types/types/index.d.ts.map +1 -0
  34. package/dist/types/utils/Logger.d.ts +88 -0
  35. package/dist/types/utils/Logger.d.ts.map +1 -0
  36. package/package.json +4 -3
  37. package/rollup.config.js +11 -2
  38. package/src/core/Sankey.ts +3 -9
  39. package/src/index.ts +3 -3
  40. package/src/services/ConfigurationService.ts +59 -22
  41. package/src/services/RenderingService.ts +3 -3
  42. package/src/services/calculation/GraphService.ts +6 -6
  43. package/src/services/calculation/SummaryService.ts +3 -3
  44. package/src/types/index.ts +8 -1
  45. package/tsconfig.json +1 -0
@@ -1,3 +1,39 @@
1
+ /**
2
+ * Type Definitions for Energy Sankey Library
3
+ *
4
+ * Comprehensive TypeScript type definitions for energy visualization data structures,
5
+ * configuration options, service interfaces, and mathematical computation types.
6
+ *
7
+ * Key Type Categories:
8
+ * - Error types: Custom error classes with detailed context
9
+ * - Data structures: Energy data points, summaries, and flow calculations
10
+ * - Configuration: Visual constants, fuel definitions, and styling
11
+ * - Mathematical types: Graph data, positioning, and computational results
12
+ * - Service interfaces: D3 selections, render data, and layout structures
13
+ *
14
+ * Type Safety Features:
15
+ * - Immutable readonly properties for data integrity
16
+ * - Strict type constraints for fuel and sector names
17
+ * - Comprehensive interface coverage for all service operations
18
+ * - Generic types for flexible service composition
19
+ *
20
+ */
21
+ // Error types
22
+ class SankeyError extends Error {
23
+ constructor(message, code) {
24
+ super(message);
25
+ this.code = code;
26
+ this.name = 'SankeyError';
27
+ }
28
+ }
29
+ class DataValidationError extends SankeyError {
30
+ constructor(message, field) {
31
+ super(message, 'DATA_VALIDATION');
32
+ this.field = field;
33
+ this.name = 'DataValidationError';
34
+ }
35
+ }
36
+
1
37
  function ascending$1(a, b) {
2
38
  return a == null || b == null ? NaN : a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
3
39
  }
@@ -4311,42 +4347,6 @@ class EventBus {
4311
4347
  }
4312
4348
  }
4313
4349
 
4314
- /**
4315
- * Type Definitions for Energy Sankey Library
4316
- *
4317
- * Comprehensive TypeScript type definitions for energy visualization data structures,
4318
- * configuration options, service interfaces, and mathematical computation types.
4319
- *
4320
- * Key Type Categories:
4321
- * - Error types: Custom error classes with detailed context
4322
- * - Data structures: Energy data points, summaries, and flow calculations
4323
- * - Configuration: Visual constants, fuel definitions, and styling
4324
- * - Mathematical types: Graph data, positioning, and computational results
4325
- * - Service interfaces: D3 selections, render data, and layout structures
4326
- *
4327
- * Type Safety Features:
4328
- * - Immutable readonly properties for data integrity
4329
- * - Strict type constraints for fuel and sector names
4330
- * - Comprehensive interface coverage for all service operations
4331
- * - Generic types for flexible service composition
4332
- *
4333
- */
4334
- // Error types
4335
- class SankeyError extends Error {
4336
- constructor(message, code) {
4337
- super(message);
4338
- this.code = code;
4339
- this.name = 'SankeyError';
4340
- }
4341
- }
4342
- class DataValidationError extends SankeyError {
4343
- constructor(message, field) {
4344
- super(message, 'DATA_VALIDATION');
4345
- this.field = field;
4346
- this.name = 'DataValidationError';
4347
- }
4348
- }
4349
-
4350
4350
  /**
4351
4351
  * Performance Monitoring and Debug Logging Utility
4352
4352
  *
@@ -4488,22 +4488,22 @@ class ConfigurationService {
4488
4488
  // ===================== COORDINATE POSITIONING CONSTANTS =====================
4489
4489
  // LEFT COLUMN POSITIONING: Fuel source boxes alignment
4490
4490
  this.LEFT_X = 10; // X-coordinate for left column (fuel sources)
4491
- this.TOP_Y = 100; // Y-coordinate for top margin (visual breathing space)
4491
+ this.LEFT_Y = 100; // Y-coordinate for top margin (visual breathing space)
4492
4492
  // ==================== MATHEMATICAL SCALING CONSTANTS ====================
4493
4493
  // ENERGY-TO-PIXEL CONVERSION: Critical scaling factor for proportional representation
4494
4494
  this.SCALE = 0.02; // Converts Quads to pixels: 1 Quad = 0.02 pixels height
4495
4495
  // Calibrated for typical US energy consumption (0-100+ Quads)
4496
4496
  // Example: 50 Quads × 0.02 = 1.0 pixel height
4497
4497
  // ELECTRICITY BOX POSITIONING: Special coordinates for electricity box (bidirectional flows)
4498
- this.ELEC_BOX_X = 320;
4499
- this.ELEC_BOX_Y = 120;
4498
+ this.ELECTRICITY_BOX_X = 320;
4499
+ this.ELECTRICITY_BOX_Y = 120;
4500
4500
  this.HEAT_BOX_X = 750;
4501
4501
  this.HEAT_BOX_Y = 200;
4502
- // X=350: Positioned between fuel sources (left) and sectors (right)
4503
- // Y=120: Offset below title area for visual clarity
4504
4502
  // ======================== VISUAL SPACING CONSTANTS ========================
4505
4503
  // VERTICAL GAPS: Spacing between stacked elements for visual clarity
4506
4504
  this.LEFT_GAP = 30; // Gap between fuel boxes (left column)
4505
+ // ANIMATION PARAMETERS: Timing and transition control
4506
+ this.SPEED = 200; // Animation speed in milliseconds (from user options, default 200)
4507
4507
  this.BLEED = 0.5; // Edge bleed factor for smooth visual transitions
4508
4508
  // =================== GEOMETRIC CALCULATION CONSTANTS ===================
4509
4509
  // MATHEMATICS: Mathematical constants
@@ -4513,7 +4513,7 @@ class ConfigurationService {
4513
4513
  // FLOW PATH SPACING: Visual separation between parallel energy flows
4514
4514
  this.PATH_GAP = 20; // Pixel gap between parallel flow paths
4515
4515
  // Prevents visual overlap while maintaining readability
4516
- this.ELEC_GAP = 19; // Special gap for electricity flows (slightly smaller)
4516
+ this.ELECTRICITY_GAP = 19; // Special gap for electricity flows (slightly smaller)
4517
4517
  // Optimized for electricity box's central position
4518
4518
  // ====================== ENERGY SOURCE DEFINITIONS ======================
4519
4519
  // Comprehensive fuel type configuration with energy industry standard categorization
@@ -4565,7 +4565,30 @@ class ConfigurationService {
4565
4565
  this.FUEL_NAMES = this.FUELS.map(fuel => fuel.fuel);
4566
4566
  // Calculate computed properties
4567
4567
  this.RIGHT_GAP = this.LEFT_GAP * 2.1;
4568
- this.SPEED = options.animationSpeed || 200;
4568
+ if (options.animationSpeed) {
4569
+ this.SPEED = options.animationSpeed;
4570
+ }
4571
+ if (options.scale) {
4572
+ this.SCALE = options.scale;
4573
+ }
4574
+ if (options.leftX) {
4575
+ this.LEFT_X = options.leftX;
4576
+ }
4577
+ if (options.leftY) {
4578
+ this.LEFT_Y = options.leftY;
4579
+ }
4580
+ if (options.electricityBoxX) {
4581
+ this.ELECTRICITY_BOX_X = options.electricityBoxX;
4582
+ }
4583
+ if (options.electricityBoxY) {
4584
+ this.ELECTRICITY_BOX_Y = options.electricityBoxY;
4585
+ }
4586
+ if (options.heatBoxX) {
4587
+ this.HEAT_BOX_X = options.heatBoxX;
4588
+ }
4589
+ if (options.heatBoxY) {
4590
+ this.HEAT_BOX_Y = options.heatBoxY;
4591
+ }
4569
4592
  this.FLOW_PATHS_ORDER = {
4570
4593
  "elec": this.BOXES_DEFAULT_FLOW_PATHS_ORDER,
4571
4594
  "heat": this.BOXES_DEFAULT_FLOW_PATHS_ORDER,
@@ -4737,43 +4760,55 @@ class ConfigurationService {
4737
4760
  validateConfiguration() {
4738
4761
  // Validate dimensions
4739
4762
  if (this.WIDTH <= 0 || this.HEIGHT <= 0) {
4740
- throw new Error('ConfigurationService: Invalid dimensions');
4763
+ throw new Error('Invalid dimensions');
4741
4764
  }
4742
4765
  // Validate box positioning
4743
4766
  if (this.BOX_WIDTH <= 0 || this.BOX_HEIGHT <= 0) {
4744
- throw new Error('ConfigurationService: Invalid box dimensions');
4767
+ throw new Error('Invalid box dimensions');
4768
+ }
4769
+ // Validate scaling factors
4770
+ if (this.SPEED <= 0) {
4771
+ throw new Error('Invalid animation speed');
4745
4772
  }
4746
4773
  // Validate scaling factors
4747
4774
  if (this.SCALE <= 0) {
4748
- throw new Error('ConfigurationService: Invalid scale factor');
4775
+ throw new Error('Invalid scale factor');
4776
+ }
4777
+ // Validate left source positioning
4778
+ if (this.LEFT_X <= 0 || this.LEFT_Y <= 0) {
4779
+ throw new Error('Invalid left sources position');
4749
4780
  }
4750
4781
  // Validate electricity box positioning
4751
- if (this.ELEC_BOX_X <= 0 || this.ELEC_BOX_X <= 0) {
4752
- throw new Error('ConfigurationService: Invalid electricity box position');
4782
+ if (this.ELECTRICITY_BOX_X <= 0 || this.ELECTRICITY_BOX_Y <= 0) {
4783
+ throw new Error('Invalid electricity box position');
4784
+ }
4785
+ // Validate heat box positioning
4786
+ if (this.HEAT_BOX_X <= 0 || this.HEAT_BOX_Y <= 0) {
4787
+ throw new Error('Invalid heat box position');
4753
4788
  }
4754
4789
  // Validate fuel definitions
4755
4790
  if (this.FUELS.length === 0) {
4756
- throw new Error('ConfigurationService: No fuels defined');
4791
+ throw new Error('No fuels defined');
4757
4792
  }
4758
4793
  // Validate sector definitions
4759
4794
  if (this.BOXES.length === 0) {
4760
- throw new Error('ConfigurationService: No sectors defined');
4795
+ throw new Error('No sectors defined');
4761
4796
  }
4762
4797
  // Validate required fuels exist
4763
4798
  const requiredFuels = ['elec', 'solar', 'nuclear', 'hydro', 'wind', 'geo', 'gas', 'coal', 'bio', 'petro'];
4764
4799
  for (const fuel of requiredFuels) {
4765
4800
  if (!this.FUEL_NAMES.includes(fuel)) {
4766
- console.warn(`ConfigurationService: Missing required fuel: ${fuel}`);
4801
+ console.warn(`Missing required fuel: ${fuel}`);
4767
4802
  }
4768
4803
  }
4769
4804
  // Validate required sectors exist
4770
4805
  const requiredSectors = ['elec', 'res', 'ag', 'indus', 'trans'];
4771
4806
  for (const sector of requiredSectors) {
4772
4807
  if (!this.BOX_NAMES.includes(sector)) {
4773
- console.warn(`ConfigurationService: Missing required sector: ${sector}`);
4808
+ console.warn(`Missing required sector: ${sector}`);
4774
4809
  }
4775
4810
  }
4776
- this.logger.log('ConfigurationService: All configuration validated successfully');
4811
+ this.logger.log('All configuration validated successfully');
4777
4812
  }
4778
4813
  // ==================== UTILITY METHODS ====================
4779
4814
  /**
@@ -5425,9 +5460,9 @@ class SummaryService {
5425
5460
  // Measured improvement: 5-10% reduction in execution time
5426
5461
  const FUELS = this.configService.FUELS; // Energy source types array
5427
5462
  const BOX_NAMES = this.configService.BOX_NAMES; // Consumption sector names
5428
- const ELEC_BOX_Y = this.configService.ELEC_BOX_Y; // Electricity box Y-coordinate
5463
+ const ELEC_BOX_Y = this.configService.ELECTRICITY_BOX_Y; // Electricity box Y-coordinate
5429
5464
  const HEAT_BOX_Y = this.configService.HEAT_BOX_Y; // Heat box Y-coordinate
5430
- const TOP_Y = this.configService.TOP_Y; // Top margin for fuel labels
5465
+ const TOP_Y = this.configService.LEFT_Y; // Top margin for fuel labels
5431
5466
  const SCALE = this.configService.SCALE; // Energy-to-pixel conversion (0.02)
5432
5467
  const LEFT_GAP = this.configService.LEFT_GAP; // Visual gap between fuel boxes
5433
5468
  // RESULT ARRAYS: Initialize output data structures
@@ -5647,7 +5682,7 @@ class SummaryService {
5647
5682
  // ELEC_BOX_Y: Base Y-coordinate for electricity box (right-hand column)
5648
5683
  // +50: Visual offset below electricity box for residential sector
5649
5684
  this.boxTops = {
5650
- res: this.configService.ELEC_BOX_Y + 50, // Base position for residential
5685
+ res: this.configService.ELECTRICITY_BOX_Y + 50, // Base position for residential
5651
5686
  heat: this.configService.HEAT_BOX_Y + 50, // Base position for residential
5652
5687
  ag: 0, // Will be calculated based on residential
5653
5688
  indus: 0, // Will be calculated based on agriculture
@@ -5753,13 +5788,13 @@ class GraphService {
5753
5788
  // Eliminates repeated property access during O(n³) loop execution
5754
5789
  // Performance improvement: 5-10% reduction in execution time
5755
5790
  const SCALE = this.configService.SCALE; // Energy-to-pixel conversion (0.02)
5756
- const ELEC_BOX_X = this.configService.ELEC_BOX_X; // Electricity box X-coordinate
5757
- const ELEC_BOX_Y = this.configService.ELEC_BOX_Y; // Electricity box Y-coordinate
5791
+ const ELEC_BOX_X = this.configService.ELECTRICITY_BOX_X; // Electricity box X-coordinate
5792
+ const ELEC_BOX_Y = this.configService.ELECTRICITY_BOX_Y; // Electricity box Y-coordinate
5758
5793
  const HEAT_BOX_X = this.configService.HEAT_BOX_X; // Heat box X-coordinate
5759
5794
  const HEAT_BOX_Y = this.configService.HEAT_BOX_Y; // Heat box Y-coordinate
5760
5795
  const BOX_WIDTH = this.configService.BOX_WIDTH; // Standard box width
5761
5796
  const LEFT_X = this.configService.LEFT_X; // Left column X-coordinate
5762
- const TOP_Y = this.configService.TOP_Y; // Top margin Y-coordinate
5797
+ const TOP_Y = this.configService.LEFT_Y; // Top margin Y-coordinate
5763
5798
  const SR3 = this.configService.SR3; // Slope ratio (height/3)
5764
5799
  const PATH_GAP = this.configService.PATH_GAP; // Visual gap between flow paths
5765
5800
  const LEFT_GAP = this.configService.LEFT_GAP; // Gap between fuel boxes
@@ -6004,7 +6039,7 @@ class GraphService {
6004
6039
  const BOX_WIDTH = this.configService.BOX_WIDTH;
6005
6040
  const SCALE = this.configService.SCALE;
6006
6041
  const SR3 = this.configService.SR3;
6007
- const ELEC_GAP = this.configService.ELEC_GAP;
6042
+ const ELEC_GAP = this.configService.ELECTRICITY_GAP;
6008
6043
  const HSR3 = this.configService.HSR3;
6009
6044
  for (let i = 0; i < this.graphs.length; ++i) {
6010
6045
  let current_box = null;
@@ -6036,8 +6071,8 @@ class GraphService {
6036
6071
  const BOX_WIDTH = this.configService.BOX_WIDTH;
6037
6072
  const SR3 = this.configService.SR3;
6038
6073
  const HSR3 = this.configService.HSR3;
6039
- const ELEC_GAP = this.configService.ELEC_GAP;
6040
- const ELEC_BOX_Y = this.configService.ELEC_BOX_Y;
6074
+ const ELEC_GAP = this.configService.ELECTRICITY_GAP;
6075
+ const ELEC_BOX_Y = this.configService.ELECTRICITY_BOX_Y;
6041
6076
  for (let i = 0; i < this.graphs.length; ++i) {
6042
6077
  let current_box = null;
6043
6078
  this.graphs[i].graph
@@ -6364,7 +6399,7 @@ class RenderingService {
6364
6399
  .attr('x', this.configService.LEFT_X) // X-position: left column alignment
6365
6400
  .attr('y', (d, i) => {
6366
6401
  // Calculate cumulative Y position for this fuel
6367
- let cumulativeTop = this.configService.TOP_Y;
6402
+ let cumulativeTop = this.configService.LEFT_Y;
6368
6403
  for (let j = 0; j < i; j++) {
6369
6404
  const prevFuel = leftFuels[j];
6370
6405
  const prevFuelTotal = totals[prevFuel.fuel] || 0;
@@ -6420,8 +6455,8 @@ class RenderingService {
6420
6455
  // CONDITIONAL POSITIONING ALGORITHM: Electricity vs. Regular Sectors
6421
6456
  if (boxConfig.box === 'elec') {
6422
6457
  // ELECTRICITY BOX: Special central positioning
6423
- x = this.configService.ELEC_BOX_X; // Configured X-position
6424
- y = this.configService.ELEC_BOX_Y - totals.elec * this.configService.SCALE; // Dynamic Y-position
6458
+ x = this.configService.ELECTRICITY_BOX_X; // Configured X-position
6459
+ y = this.configService.ELECTRICITY_BOX_Y - totals.elec * this.configService.SCALE; // Dynamic Y-position
6425
6460
  }
6426
6461
  else if (boxConfig.box === 'heat') {
6427
6462
  // ELECTRICITY BOX: Special central positioning
@@ -6776,7 +6811,6 @@ class Sankey {
6776
6811
  timestamp: Date.now(),
6777
6812
  source: 'SankeyVisualization',
6778
6813
  data: {
6779
- version: '7.0.0',
6780
6814
  services: [], // Will be populated as services come online
6781
6815
  initTime: 0 // Will be updated when initialization completes
6782
6816
  }
@@ -6827,7 +6861,6 @@ class Sankey {
6827
6861
  timestamp: Date.now(),
6828
6862
  source: 'SankeyVisualization',
6829
6863
  data: {
6830
- version: '7.0.0',
6831
6864
  totalInitTime: totalInitializationTime,
6832
6865
  dataPointCount: this.options.data.length,
6833
6866
  yearRange: [
@@ -7163,7 +7196,7 @@ class Sankey {
7163
7196
  waste: {}
7164
7197
  };
7165
7198
  for (let i = 0; i < graphs.length; ++i) {
7166
- let top = this.services.configurationService.TOP_Y;
7199
+ let top = this.services.configurationService.LEFT_Y;
7167
7200
  const y = graphs[i].year;
7168
7201
  graphNest.strokes[y] = {};
7169
7202
  graphNest.tops[y] = {};
@@ -7174,7 +7207,7 @@ class Sankey {
7174
7207
  const f = fuel.fuel;
7175
7208
  graphNest.strokes[y][f] = {};
7176
7209
  if (f == 'elec') {
7177
- graphNest.tops[y][f] = this.services.configurationService.ELEC_BOX_Y - summary.totals[i].elec * SCALE;
7210
+ graphNest.tops[y][f] = this.services.configurationService.ELECTRICITY_BOX_Y - summary.totals[i].elec * SCALE;
7178
7211
  }
7179
7212
  else if (f == 'heat') {
7180
7213
  graphNest.tops[y][f] = this.services.configurationService.HEAT_BOX_Y - summary.totals[i].heat * SCALE;
@@ -7498,16 +7531,12 @@ class Sankey {
7498
7531
  mergeOptionsWithDefaults(options) {
7499
7532
  // Merge user options with system defaults
7500
7533
  return {
7501
- data: options.data,
7502
- country: options.country,
7534
+ ...options,
7503
7535
  includeControls: options.includeControls !== false,
7504
7536
  includeTimeline: options.includeTimeline !== false,
7505
7537
  includeWasteToggle: options.includeWasteToggle !== false,
7506
7538
  autoPlay: options.autoPlay || false,
7507
7539
  showWasteHeat: options.showWasteHeat !== false,
7508
- animationSpeed: options.animationSpeed || 200,
7509
- width: options.width || null,
7510
- height: options.height || 620,
7511
7540
  loopAnimation: options.loopAnimation !== undefined ? options.loopAnimation : false
7512
7541
  };
7513
7542
  }
@@ -8338,8 +8367,8 @@ class AnimationService {
8338
8367
  }
8339
8368
 
8340
8369
  var AnimationService$1 = /*#__PURE__*/Object.freeze({
8341
- __proto__: null,
8342
- AnimationService: AnimationService
8370
+ __proto__: null,
8371
+ AnimationService: AnimationService
8343
8372
  });
8344
8373
 
8345
8374
  /**
@@ -9145,9 +9174,9 @@ class InteractionService {
9145
9174
  }
9146
9175
 
9147
9176
  var InteractionService$1 = /*#__PURE__*/Object.freeze({
9148
- __proto__: null,
9149
- InteractionService: InteractionService
9177
+ __proto__: null,
9178
+ InteractionService: InteractionService
9150
9179
  });
9151
9180
 
9152
- export { Sankey as default };
9181
+ export { DataValidationError, SankeyError, Sankey as default };
9153
9182
  //# sourceMappingURL=sankey.esm.js.map