mdas-jsview-sdk 1.0.9-uat.0 → 1.0.11-uat.0

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.
@@ -1766,7 +1766,7 @@ const SharedStyles = `
1766
1766
  .widget {
1767
1767
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
1768
1768
  width: 100%;
1769
- max-width: 800px;
1769
+ max-width: 1400px;
1770
1770
  }
1771
1771
 
1772
1772
  /* HEADER STYLES */
@@ -2620,7 +2620,7 @@ const OptionsStyles = `
2620
2620
  .options-widget {
2621
2621
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
2622
2622
  color: #333;
2623
- max-width: 800px;
2623
+ max-width: 1400px;
2624
2624
  width: 100%;
2625
2625
  margin: 0 auto;
2626
2626
  position: relative;
@@ -37720,11 +37720,26 @@ class IntradayChartWidget extends BaseWidget {
37720
37720
  });
37721
37721
  }
37722
37722
  addStyles() {
37723
+ // Skip style injection if external styles are detected or explicitly disabled
37724
+ if (this.options.skipStyleInjection || document.querySelector('link[href*="mdas-styles.css"]')) {
37725
+ if (this.debug) {
37726
+ console.log('[IntradayChartWidget] Skipping style injection - external styles detected');
37727
+ }
37728
+ return;
37729
+ }
37723
37730
  if (!document.querySelector('#intraday-chart-styles')) {
37724
- const styleSheet = document.createElement('style');
37725
- styleSheet.id = 'intraday-chart-styles';
37726
- styleSheet.textContent = IntradayChartStyles;
37727
- document.head.appendChild(styleSheet);
37731
+ try {
37732
+ const styleSheet = document.createElement('style');
37733
+ styleSheet.id = 'intraday-chart-styles';
37734
+ styleSheet.textContent = IntradayChartStyles;
37735
+ document.head.appendChild(styleSheet);
37736
+ if (this.debug) {
37737
+ console.log('[IntradayChartWidget] Styles injected successfully');
37738
+ }
37739
+ } catch (error) {
37740
+ console.warn('[IntradayChartWidget] Failed to inject styles:', error);
37741
+ console.warn('[IntradayChartWidget] Please add <link rel="stylesheet" href="mdas-styles.css"> to your HTML');
37742
+ }
37728
37743
  }
37729
37744
  }
37730
37745
  async loadChartData() {
@@ -38174,16 +38189,28 @@ class IntradayChartWidget extends BaseWidget {
38174
38189
 
38175
38190
  if (this.chartType === 'candlestick') {
38176
38191
  // Prepare OHLC data for candlestick chart
38177
- chartDataPoints = validDataPoints.map(point => ({
38178
- x: this.parseTimestamp(point.time).getTime(),
38179
- o: point.open,
38180
- h: point.high,
38181
- l: point.low,
38182
- c: point.close
38183
- })).filter(point => {
38184
- // Filter out invalid timestamps
38185
- return !isNaN(point.x) && point.x > 0;
38186
- });
38192
+ if (this.rangeBack > 0) {
38193
+ // For multi-day charts, use index as x-value (linear scale)
38194
+ chartDataPoints = validDataPoints.map((point, index) => ({
38195
+ x: index,
38196
+ o: point.open,
38197
+ h: point.high,
38198
+ l: point.low,
38199
+ c: point.close
38200
+ }));
38201
+ } else {
38202
+ // For single-day charts, use timestamps (time scale)
38203
+ chartDataPoints = validDataPoints.map(point => ({
38204
+ x: this.parseTimestamp(point.time).getTime(),
38205
+ o: point.open,
38206
+ h: point.high,
38207
+ l: point.low,
38208
+ c: point.close
38209
+ })).filter(point => {
38210
+ // Filter out invalid timestamps
38211
+ return !isNaN(point.x) && point.x > 0;
38212
+ });
38213
+ }
38187
38214
  if (chartDataPoints.length === 0) {
38188
38215
  console.error('[IntradayChartWidget] No valid candlestick data points after date parsing');
38189
38216
  this.showError('Unable to parse chart data timestamps');
@@ -38205,14 +38232,23 @@ class IntradayChartWidget extends BaseWidget {
38205
38232
  };
38206
38233
  } else {
38207
38234
  // Prepare data with timestamps for line/area chart
38208
- chartDataPoints = validDataPoints.map(point => ({
38209
- x: this.parseTimestamp(point.time),
38210
- y: point.close
38211
- })).filter(point => {
38212
- // Filter out invalid dates
38213
- const timestamp = point.x.getTime();
38214
- return !isNaN(timestamp) && timestamp > 0;
38215
- });
38235
+ if (this.rangeBack > 0) {
38236
+ // For multi-day charts, use index as x-value (linear scale)
38237
+ chartDataPoints = validDataPoints.map((point, index) => ({
38238
+ x: index,
38239
+ y: point.close
38240
+ }));
38241
+ } else {
38242
+ // For single-day charts, use timestamps (time scale)
38243
+ chartDataPoints = validDataPoints.map(point => ({
38244
+ x: this.parseTimestamp(point.time),
38245
+ y: point.close
38246
+ })).filter(point => {
38247
+ // Filter out invalid dates
38248
+ const timestamp = point.x.getTime();
38249
+ return !isNaN(timestamp) && timestamp > 0;
38250
+ });
38251
+ }
38216
38252
  if (chartDataPoints.length === 0) {
38217
38253
  console.error('[IntradayChartWidget] No valid chart data points after date parsing');
38218
38254
  this.showError('Unable to parse chart data timestamps');
@@ -38247,16 +38283,23 @@ class IntradayChartWidget extends BaseWidget {
38247
38283
  console.log('[IntradayChartWidget] Last data point - Source time:', validDataPoints[validDataPoints.length - 1].time);
38248
38284
  console.log('[IntradayChartWidget] Last chart point:', chartDataPoints[chartDataPoints.length - 1]);
38249
38285
 
38250
- // Calculate explicit min/max for x-axis to prevent Chart.js from auto-calculating incorrectly
38251
- const timestamps = chartDataPoints.map(p => this.chartType === 'candlestick' ? p.x : p.x.getTime());
38252
- const minTimestamp = Math.min(...timestamps);
38253
- const maxTimestamp = Math.max(...timestamps);
38254
- console.log('[IntradayChartWidget] X-axis bounds:', {
38255
- min: minTimestamp,
38256
- max: maxTimestamp,
38257
- minDate: new Date(minTimestamp),
38258
- maxDate: new Date(maxTimestamp)
38259
- });
38286
+ // Calculate explicit min/max for x-axis (only for time scale, not linear)
38287
+ let minTimestamp, maxTimestamp;
38288
+ if (this.rangeBack === 0) {
38289
+ // For time scale, calculate timestamp bounds
38290
+ const timestamps = chartDataPoints.map(p => this.chartType === 'candlestick' ? p.x : p.x.getTime());
38291
+ minTimestamp = Math.min(...timestamps);
38292
+ maxTimestamp = Math.max(...timestamps);
38293
+ console.log('[IntradayChartWidget] X-axis bounds:', {
38294
+ min: minTimestamp,
38295
+ max: maxTimestamp,
38296
+ minDate: new Date(minTimestamp),
38297
+ maxDate: new Date(maxTimestamp)
38298
+ });
38299
+ } else {
38300
+ // For linear scale, bounds are just indices
38301
+ console.log('[IntradayChartWidget] Using linear scale with', chartDataPoints.length, 'data points');
38302
+ }
38260
38303
  const config = {
38261
38304
  type: this.chartType === 'candlestick' ? 'candlestick' : 'line',
38262
38305
  data: {
@@ -38294,10 +38337,9 @@ class IntradayChartWidget extends BaseWidget {
38294
38337
  const index = context[0].dataIndex;
38295
38338
  const point = validDataPoints[index];
38296
38339
  if (point) {
38297
- // Format timestamp for tooltip
38340
+ // Display timestamp as-is from the data, without timezone conversion
38298
38341
  const date = new Date(point.time);
38299
38342
  return date.toLocaleString('en-US', {
38300
- timeZone: 'America/New_York',
38301
38343
  month: '2-digit',
38302
38344
  day: '2-digit',
38303
38345
  year: 'numeric',
@@ -38348,62 +38390,60 @@ class IntradayChartWidget extends BaseWidget {
38348
38390
  }
38349
38391
  },
38350
38392
  annotation: {
38351
- annotations: {
38352
- livePriceLine: {
38353
- type: 'line',
38354
- scaleID: 'y',
38355
- value: this.livePrice || stats.close,
38356
- borderColor: '#667eea',
38357
- borderWidth: 2,
38358
- borderDash: [5, 5],
38359
- label: {
38360
- display: true,
38361
- content: this.livePrice ? `$${this.livePrice.toFixed(2)}` : `$${stats.close.toFixed(2)}`,
38362
- enabled: true,
38363
- position: 'end',
38364
- backgroundColor: 'rgb(102, 126, 234)',
38365
- color: '#ffffff',
38366
- font: {
38367
- size: 12,
38368
- weight: 'bold',
38369
- family: 'system-ui, -apple-system, sans-serif'
38370
- },
38371
- padding: {
38372
- top: 4,
38373
- bottom: 4,
38374
- left: 8,
38375
- right: 8
38376
- },
38377
- borderRadius: 4,
38378
- xAdjust: -10,
38379
- yAdjust: 0
38380
- }
38381
- }
38382
- }
38393
+ annotations: this.createAnnotations(validDataPoints, stats)
38383
38394
  }
38384
38395
  },
38385
38396
  scales: {
38386
38397
  x: {
38387
- type: 'time',
38388
- min: minTimestamp,
38389
- max: maxTimestamp,
38390
- time: {
38391
- unit: this.rangeBack === 0 ? 'minute' : 'hour',
38398
+ type: this.rangeBack === 0 ? 'time' : 'linear',
38399
+ min: this.rangeBack === 0 ? minTimestamp : undefined,
38400
+ max: this.rangeBack === 0 ? maxTimestamp : undefined,
38401
+ time: this.rangeBack === 0 ? {
38402
+ unit: 'hour',
38403
+ stepSize: 1,
38392
38404
  displayFormats: {
38393
- minute: 'h:mm a',
38394
- hour: 'MMM d, ha'
38405
+ hour: 'h:mm a'
38395
38406
  },
38396
38407
  tooltipFormat: 'MMM d, h:mm a'
38397
- },
38408
+ } : undefined,
38398
38409
  grid: {
38399
38410
  display: false
38400
38411
  },
38401
38412
  ticks: {
38402
- maxTicksLimit: 10,
38413
+ maxTicksLimit: this.rangeBack === 0 ? 10 : 8,
38403
38414
  color: '#6b7280',
38404
38415
  autoSkip: true,
38405
38416
  maxRotation: 0,
38406
- minRotation: 0
38417
+ minRotation: 0,
38418
+ callback: (value, index) => {
38419
+ if (this.rangeBack > 0) {
38420
+ // For multi-day charts with linear scale, show actual time from data point
38421
+ const point = validDataPoints[index];
38422
+ if (point) {
38423
+ const date = new Date(point.time);
38424
+ return date.toLocaleString('en-US', {
38425
+ month: 'short',
38426
+ day: 'numeric',
38427
+ hour: 'numeric',
38428
+ minute: '2-digit',
38429
+ hour12: true
38430
+ });
38431
+ }
38432
+ return '';
38433
+ }
38434
+ // For single-day time scale, provide fallback formatting
38435
+ // If value is a number (timestamp), format it
38436
+ if (typeof value === 'number') {
38437
+ const date = new Date(value);
38438
+ return date.toLocaleString('en-US', {
38439
+ hour: 'numeric',
38440
+ minute: '2-digit',
38441
+ hour12: true
38442
+ });
38443
+ }
38444
+ // Otherwise let Chart.js handle it (if date adapter is working)
38445
+ return value;
38446
+ }
38407
38447
  }
38408
38448
  },
38409
38449
  y: {
@@ -38449,6 +38489,63 @@ class IntradayChartWidget extends BaseWidget {
38449
38489
  // Add reset zoom button listener
38450
38490
  this.setupZoomReset();
38451
38491
  }
38492
+ createAnnotations(dataPoints, stats) {
38493
+ const annotations = {
38494
+ livePriceLine: {
38495
+ type: 'line',
38496
+ scaleID: 'y',
38497
+ value: this.livePrice || stats.close,
38498
+ borderColor: '#667eea',
38499
+ borderWidth: 2,
38500
+ borderDash: [5, 5],
38501
+ label: {
38502
+ display: true,
38503
+ content: this.livePrice ? `$${this.livePrice.toFixed(2)}` : `$${stats.close.toFixed(2)}`,
38504
+ enabled: true,
38505
+ position: 'end',
38506
+ backgroundColor: 'rgb(102, 126, 234)',
38507
+ color: '#ffffff',
38508
+ font: {
38509
+ size: 12,
38510
+ weight: 'bold',
38511
+ family: 'system-ui, -apple-system, sans-serif'
38512
+ },
38513
+ padding: {
38514
+ top: 4,
38515
+ bottom: 4,
38516
+ left: 8,
38517
+ right: 8
38518
+ },
38519
+ borderRadius: 4,
38520
+ xAdjust: -10,
38521
+ yAdjust: 0
38522
+ }
38523
+ }
38524
+ };
38525
+
38526
+ // Add day separators for multi-day charts (5D, etc.)
38527
+ if (this.rangeBack > 0 && dataPoints.length > 0) {
38528
+ let currentDay = null;
38529
+ dataPoints.forEach((point, index) => {
38530
+ const pointDate = new Date(point.time);
38531
+ const day = pointDate.toDateString();
38532
+
38533
+ // Add vertical line at the start of each new day
38534
+ if (currentDay !== day && currentDay !== null) {
38535
+ annotations[`daySeparator${index}`] = {
38536
+ type: 'line',
38537
+ scaleID: 'x',
38538
+ value: index,
38539
+ borderColor: 'rgba(0, 0, 0, 0.1)',
38540
+ borderWidth: 1,
38541
+ borderDash: [3, 3]
38542
+ };
38543
+ }
38544
+ currentDay = day;
38545
+ });
38546
+ }
38547
+ return annotations;
38548
+ }
38452
38549
  setupZoomReset() {
38453
38550
  const resetBtn = this.container.querySelector('.zoom-reset-btn');
38454
38551
  if (resetBtn) {