maidr 2.7.1 → 2.8.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.
- package/dist/maidr.js +148 -153
- package/dist/maidr.min.js +1 -1
- package/package.json +1 -1
package/dist/maidr.js
CHANGED
|
@@ -88,6 +88,7 @@ class Constants {
|
|
|
88
88
|
skillLevel = 'basic'; // basic / intermediate / expert
|
|
89
89
|
skillLevelOther = ''; // custom skill level
|
|
90
90
|
autoInitLLM = true; // auto initialize LLM on page load
|
|
91
|
+
verboseText = '';
|
|
91
92
|
|
|
92
93
|
// user controls (not exposed to menu, with shortcuts usually)
|
|
93
94
|
showDisplay = 1; // true / false
|
|
@@ -924,6 +925,7 @@ class ChatLLM {
|
|
|
924
925
|
constructor() {
|
|
925
926
|
this.firstTime = true;
|
|
926
927
|
this.firstMulti = true;
|
|
928
|
+
this.firstOpen = true;
|
|
927
929
|
this.shown = false;
|
|
928
930
|
this.CreateComponent();
|
|
929
931
|
this.SetEvents();
|
|
@@ -1157,7 +1159,11 @@ class ChatLLM {
|
|
|
1157
1159
|
// kill more than 2 newlines in a row
|
|
1158
1160
|
markdown = markdown.replace(/\n{3,}/g, '\n\n');
|
|
1159
1161
|
|
|
1160
|
-
|
|
1162
|
+
try {
|
|
1163
|
+
navigator.clipboard.writeText(markdown);
|
|
1164
|
+
} catch (err) {
|
|
1165
|
+
console.error('Failed to copy: ', err);
|
|
1166
|
+
}
|
|
1161
1167
|
return markdown;
|
|
1162
1168
|
}
|
|
1163
1169
|
}
|
|
@@ -1219,14 +1225,30 @@ class ChatLLM {
|
|
|
1219
1225
|
* @returns {void}
|
|
1220
1226
|
*/
|
|
1221
1227
|
async Submit(text, firsttime = false) {
|
|
1228
|
+
// misc init
|
|
1229
|
+
let img = null;
|
|
1230
|
+
this.firstMulti = true;
|
|
1231
|
+
|
|
1232
|
+
// if this is the user's first message (or we're gemini, in which case we need to send every time), prepend prompt with user position
|
|
1233
|
+
if (
|
|
1234
|
+
(this.firstOpen || constants.LLMModel == 'gemini') &&
|
|
1235
|
+
!firsttime &&
|
|
1236
|
+
constants.verboseText.length > 0
|
|
1237
|
+
) {
|
|
1238
|
+
text =
|
|
1239
|
+
"Here is the current position in the chart; no response necessarily needed, use this info only if it's relevant to future questions: " +
|
|
1240
|
+
constants.verboseText +
|
|
1241
|
+
'. My question is: ' +
|
|
1242
|
+
text;
|
|
1243
|
+
|
|
1244
|
+
this.firstOpen = false;
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1222
1247
|
// start waiting sound
|
|
1223
1248
|
if (constants.playLLMWaitingSound) {
|
|
1224
1249
|
this.WaitingSound(true);
|
|
1225
1250
|
}
|
|
1226
1251
|
|
|
1227
|
-
let img = null;
|
|
1228
|
-
this.firstMulti = true;
|
|
1229
|
-
|
|
1230
1252
|
if (constants.LLMOpenAiMulti || constants.LLMModel == 'openai') {
|
|
1231
1253
|
if (firsttime) {
|
|
1232
1254
|
img = await this.ConvertSVGtoJPG(singleMaidr.id, 'openai');
|
|
@@ -1640,6 +1662,7 @@ class ChatLLM {
|
|
|
1640
1662
|
document.getElementById('chatLLM_modal_backdrop').classList.add('hidden');
|
|
1641
1663
|
this.whereWasMyFocus.focus();
|
|
1642
1664
|
this.whereWasMyFocus = null;
|
|
1665
|
+
this.firstOpen = true;
|
|
1643
1666
|
}
|
|
1644
1667
|
}
|
|
1645
1668
|
|
|
@@ -2305,7 +2328,7 @@ class Tracker {
|
|
|
2305
2328
|
//console.log("x_tickmark: '", x_tickmark, "', y_tickmark: '", y_tickmark, "', x_label: '", x_label, "', y_label: '", y_label, "', value: '", value, "', fill_value: '", fill_value);
|
|
2306
2329
|
|
|
2307
2330
|
this.SetData('events', eventToLog);
|
|
2308
|
-
console.log('logged an event');
|
|
2331
|
+
//console.log('logged an event');
|
|
2309
2332
|
}
|
|
2310
2333
|
|
|
2311
2334
|
SetData(key, value) {
|
|
@@ -3306,9 +3329,10 @@ class Display {
|
|
|
3306
3329
|
|
|
3307
3330
|
let output = '';
|
|
3308
3331
|
let verboseText = '';
|
|
3332
|
+
let terseText = '';
|
|
3309
3333
|
let reviewText = '';
|
|
3310
3334
|
if (constants.chartType == 'bar') {
|
|
3311
|
-
// {legend x} is {colname x}, {legend y} is {value y}
|
|
3335
|
+
// verbose: {legend x} is {colname x}, {legend y} is {value y}
|
|
3312
3336
|
if (plot.columnLabels[position.x]) {
|
|
3313
3337
|
if (plot.plotLegend.x.length > 0) {
|
|
3314
3338
|
verboseText += plot.plotLegend.x + ' is ';
|
|
@@ -3321,20 +3345,16 @@ class Display {
|
|
|
3321
3345
|
}
|
|
3322
3346
|
verboseText += plot.plotData[position.x];
|
|
3323
3347
|
}
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
plot.plotData[position.x] +
|
|
3333
|
-
'</p>\n';
|
|
3334
|
-
} else if (constants.textMode == 'verbose') {
|
|
3335
|
-
output += '<p>' + verboseText + '</p>\n';
|
|
3336
|
-
}
|
|
3348
|
+
// terse: {colname} {value}
|
|
3349
|
+
terseText +=
|
|
3350
|
+
'<p>' +
|
|
3351
|
+
plot.columnLabels[position.x] +
|
|
3352
|
+
' ' +
|
|
3353
|
+
plot.plotData[position.x] +
|
|
3354
|
+
'</p>\n';
|
|
3355
|
+
verboseText = '<p>' + verboseText + '</p>\n';
|
|
3337
3356
|
} else if (constants.chartType == 'heat') {
|
|
3357
|
+
// verbose
|
|
3338
3358
|
// col name and value
|
|
3339
3359
|
if (constants.navigation == 1) {
|
|
3340
3360
|
verboseText +=
|
|
@@ -3367,31 +3387,25 @@ class Display {
|
|
|
3367
3387
|
verboseText += plot.data[position.y][position.x];
|
|
3368
3388
|
// }
|
|
3369
3389
|
}
|
|
3370
|
-
// terse
|
|
3371
|
-
if (constants.
|
|
3372
|
-
//
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
plot.y_labels[position.y] +
|
|
3388
|
-
', ' +
|
|
3389
|
-
plot.data[position.y][position.x] +
|
|
3390
|
-
'</p>\n';
|
|
3391
|
-
}
|
|
3392
|
-
} else if (constants.textMode == 'verbose') {
|
|
3393
|
-
output += '<p>' + verboseText + '</p>\n';
|
|
3390
|
+
// terse: value only
|
|
3391
|
+
if (constants.navigation == 1) {
|
|
3392
|
+
// column navigation
|
|
3393
|
+
terseText +=
|
|
3394
|
+
'<p>' +
|
|
3395
|
+
plot.x_labels[position.x] +
|
|
3396
|
+
', ' +
|
|
3397
|
+
plot.data[position.y][position.x] +
|
|
3398
|
+
'</p>\n';
|
|
3399
|
+
} else {
|
|
3400
|
+
// row navigation
|
|
3401
|
+
terseText +=
|
|
3402
|
+
'<p>' +
|
|
3403
|
+
plot.y_labels[position.y] +
|
|
3404
|
+
', ' +
|
|
3405
|
+
plot.data[position.y][position.x] +
|
|
3406
|
+
'</p>\n';
|
|
3394
3407
|
}
|
|
3408
|
+
verboseText = '<p>' + verboseText + '</p>\n';
|
|
3395
3409
|
} else if (constants.chartType == 'box') {
|
|
3396
3410
|
// setup
|
|
3397
3411
|
let val = 0;
|
|
@@ -3402,8 +3416,6 @@ class Display {
|
|
|
3402
3416
|
let sectionKey = plot.GetSectionKey(
|
|
3403
3417
|
constants.plotOrientation == 'vert' ? position.y : position.x
|
|
3404
3418
|
);
|
|
3405
|
-
let textTerse = '';
|
|
3406
|
-
let textVerbose = '';
|
|
3407
3419
|
|
|
3408
3420
|
if (sectionKey == 'lower_outlier' || sectionKey == 'upper_outlier') {
|
|
3409
3421
|
isOutlier = true;
|
|
@@ -3422,67 +3434,64 @@ class Display {
|
|
|
3422
3434
|
|
|
3423
3435
|
// group label for verbose
|
|
3424
3436
|
if (constants.navigation) {
|
|
3425
|
-
if (plot.x_group_label)
|
|
3437
|
+
if (plot.x_group_label) verboseText += plot.x_group_label;
|
|
3426
3438
|
} else if (!constants.navigation) {
|
|
3427
|
-
if (plot.y_group_label)
|
|
3439
|
+
if (plot.y_group_label) verboseText += plot.y_group_label;
|
|
3428
3440
|
}
|
|
3429
3441
|
// and axes label
|
|
3430
3442
|
if (constants.navigation) {
|
|
3431
3443
|
if (plot.x_labels[plotPos]) {
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3444
|
+
verboseText += ' is ';
|
|
3445
|
+
terseText += plot.x_labels[plotPos] + ', ';
|
|
3446
|
+
verboseText += plot.x_labels[plotPos] + ', ';
|
|
3435
3447
|
} else {
|
|
3436
|
-
|
|
3448
|
+
verboseText += ', ';
|
|
3437
3449
|
}
|
|
3438
3450
|
} else if (!constants.navigation) {
|
|
3439
3451
|
if (plot.y_labels[plotPos]) {
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3452
|
+
verboseText += ' is ';
|
|
3453
|
+
terseText += plot.y_labels[plotPos] + ', ';
|
|
3454
|
+
verboseText += plot.y_labels[plotPos] + ', ';
|
|
3443
3455
|
} else {
|
|
3444
|
-
|
|
3456
|
+
verboseText += ', ';
|
|
3445
3457
|
}
|
|
3446
3458
|
}
|
|
3447
3459
|
// outliers
|
|
3448
3460
|
if (isOutlier) {
|
|
3449
|
-
|
|
3450
|
-
|
|
3461
|
+
terseText += numPoints + ' ';
|
|
3462
|
+
verboseText += numPoints + ' ';
|
|
3451
3463
|
}
|
|
3452
3464
|
// label
|
|
3453
|
-
|
|
3454
|
-
if (numPoints == 1)
|
|
3465
|
+
verboseText += resources.GetString(sectionKey);
|
|
3466
|
+
if (numPoints == 1) verboseText += ' is ';
|
|
3455
3467
|
else {
|
|
3456
|
-
|
|
3457
|
-
if (numPoints > 1)
|
|
3468
|
+
verboseText += 's ';
|
|
3469
|
+
if (numPoints > 1) verboseText += ' are ';
|
|
3458
3470
|
}
|
|
3459
3471
|
if (
|
|
3460
3472
|
isOutlier ||
|
|
3461
3473
|
(constants.navigation && constants.plotOrientation == 'horz') ||
|
|
3462
3474
|
(!constants.navigation && constants.plotOrientation == 'vert')
|
|
3463
3475
|
) {
|
|
3464
|
-
|
|
3476
|
+
terseText += resources.GetString(sectionKey);
|
|
3465
3477
|
|
|
3466
3478
|
// grammar
|
|
3467
3479
|
if (numPoints != 1) {
|
|
3468
|
-
|
|
3480
|
+
terseText += 's';
|
|
3469
3481
|
}
|
|
3470
|
-
|
|
3482
|
+
terseText += ' ';
|
|
3471
3483
|
}
|
|
3472
3484
|
// val
|
|
3473
3485
|
if (plot.plotData[plotPos][sectionKey] == null && !isOutlier) {
|
|
3474
|
-
|
|
3475
|
-
|
|
3486
|
+
terseText += 'empty';
|
|
3487
|
+
verboseText += 'empty';
|
|
3476
3488
|
} else {
|
|
3477
|
-
|
|
3478
|
-
|
|
3489
|
+
terseText += val;
|
|
3490
|
+
verboseText += val;
|
|
3479
3491
|
}
|
|
3480
3492
|
|
|
3481
|
-
verboseText =
|
|
3482
|
-
|
|
3483
|
-
output = '<p>' + textVerbose + '</p>\n';
|
|
3484
|
-
else if (constants.textMode == 'terse')
|
|
3485
|
-
output = '<p>' + textTerse + '</p>\n';
|
|
3493
|
+
verboseText = '<p>' + verboseText + '</p>\n';
|
|
3494
|
+
terseText = '<p>' + terseText + '</p>\n';
|
|
3486
3495
|
} else if (
|
|
3487
3496
|
[].concat(singleMaidr.type).includes('point') ||
|
|
3488
3497
|
[].concat(singleMaidr.type).includes('smooth')
|
|
@@ -3499,20 +3508,15 @@ class Display {
|
|
|
3499
3508
|
plot.y[position.x].join(', ') +
|
|
3500
3509
|
']';
|
|
3501
3510
|
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
']' +
|
|
3512
|
-
'</p>\n';
|
|
3513
|
-
} else if (constants.textMode == 'verbose') {
|
|
3514
|
-
// set from verboseText
|
|
3515
|
-
}
|
|
3511
|
+
// terse
|
|
3512
|
+
terseText +=
|
|
3513
|
+
'<p>' +
|
|
3514
|
+
plot.x[position.x] +
|
|
3515
|
+
', ' +
|
|
3516
|
+
'[' +
|
|
3517
|
+
plot.y[position.x].join(', ') +
|
|
3518
|
+
']' +
|
|
3519
|
+
'</p>\n';
|
|
3516
3520
|
} else if (constants.chartType == 'smooth') {
|
|
3517
3521
|
// best fit smooth layer
|
|
3518
3522
|
verboseText +=
|
|
@@ -3524,42 +3528,31 @@ class Display {
|
|
|
3524
3528
|
' ' +
|
|
3525
3529
|
plot.curvePoints[positionL1.x]; // verbose mode: x and y values
|
|
3526
3530
|
|
|
3527
|
-
|
|
3528
|
-
// do nothing
|
|
3529
|
-
} else if (constants.textMode == 'terse') {
|
|
3530
|
-
// terse mode: gradient trend
|
|
3531
|
-
// output += '<p>' + plot.gradient[positionL1.x] + '<p>\n';
|
|
3531
|
+
// terse mode: gradient trend
|
|
3532
3532
|
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
} else if (constants.textMode == 'verbose') {
|
|
3536
|
-
// set from verboseText
|
|
3537
|
-
}
|
|
3533
|
+
// display absolute gradient of the graph
|
|
3534
|
+
terseText += '<p>' + plot.curvePoints[positionL1.x] + '<p>\n';
|
|
3538
3535
|
}
|
|
3539
|
-
|
|
3540
|
-
output = '<p>' + verboseText + '</p>\n';
|
|
3536
|
+
verboseText = '<p>' + verboseText + '</p>\n';
|
|
3541
3537
|
} else if (constants.chartType == 'hist') {
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
}
|
|
3561
|
-
output += plot.plotData[position.x].y;
|
|
3562
|
-
}
|
|
3538
|
+
// terse: {x}, {y}
|
|
3539
|
+
terseText =
|
|
3540
|
+
'<p>' +
|
|
3541
|
+
plot.plotData[position.x].x +
|
|
3542
|
+
', ' +
|
|
3543
|
+
plot.plotData[position.x].y +
|
|
3544
|
+
'</p>\n';
|
|
3545
|
+
// verbose: {xlabel} is xmin through xmax, {ylabel} is y
|
|
3546
|
+
verboseText = '<p>';
|
|
3547
|
+
if (plot.legendX) {
|
|
3548
|
+
verboseText = plot.legendX + ' is ';
|
|
3549
|
+
}
|
|
3550
|
+
verboseText += plot.plotData[position.x].xmin;
|
|
3551
|
+
verboseText += ' through ' + plot.plotData[position.x].xmax + ', ';
|
|
3552
|
+
if (plot.legendY) {
|
|
3553
|
+
verboseText += plot.legendY + ' is ';
|
|
3554
|
+
}
|
|
3555
|
+
verboseText += plot.plotData[position.x].y;
|
|
3563
3556
|
} else if (constants.chartType == 'line') {
|
|
3564
3557
|
// line layer
|
|
3565
3558
|
if (plot.plotLegend) {
|
|
@@ -3571,19 +3564,15 @@ class Display {
|
|
|
3571
3564
|
}
|
|
3572
3565
|
verboseText += plot.pointValuesY[position.x];
|
|
3573
3566
|
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
} else if (constants.textMode == 'verbose') {
|
|
3584
|
-
// set from verboseText
|
|
3585
|
-
output += '<p>' + verboseText + '</p>\n';
|
|
3586
|
-
}
|
|
3567
|
+
// terse
|
|
3568
|
+
terseText +=
|
|
3569
|
+
'<p>' +
|
|
3570
|
+
plot.pointValuesX[position.x] +
|
|
3571
|
+
', ' +
|
|
3572
|
+
plot.pointValuesY[position.x] +
|
|
3573
|
+
'</p>\n';
|
|
3574
|
+
|
|
3575
|
+
verboseText = '<p>' + verboseText + '</p>\n';
|
|
3587
3576
|
} else if (
|
|
3588
3577
|
constants.chartType == 'stacked_bar' ||
|
|
3589
3578
|
constants.chartType == 'stacked_normalized_bar' ||
|
|
@@ -3600,30 +3589,33 @@ class Display {
|
|
|
3600
3589
|
verboseText += plot.fill[position.y] + ', ';
|
|
3601
3590
|
verboseText += 'value is ' + plot.plotData[position.x][position.y];
|
|
3602
3591
|
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
' is ' +
|
|
3612
|
-
plot.plotData[position.x][position.y] +
|
|
3613
|
-
'</p>\n';
|
|
3614
|
-
} else {
|
|
3615
|
-
output +=
|
|
3616
|
-
'<p>' +
|
|
3617
|
-
plot.fill[position.y] +
|
|
3618
|
-
' is ' +
|
|
3619
|
-
plot.plotData[position.x][position.y] +
|
|
3620
|
-
'</p>\n';
|
|
3621
|
-
}
|
|
3592
|
+
// navigation == 1 ? {colname x} : {colname y} is {plotData[x][y]}
|
|
3593
|
+
if (constants.navigation == 1) {
|
|
3594
|
+
terseText +=
|
|
3595
|
+
'<p>' +
|
|
3596
|
+
plot.level[position.x] +
|
|
3597
|
+
' is ' +
|
|
3598
|
+
plot.plotData[position.x][position.y] +
|
|
3599
|
+
'</p>\n';
|
|
3622
3600
|
} else {
|
|
3623
|
-
|
|
3601
|
+
terseText +=
|
|
3602
|
+
'<p>' +
|
|
3603
|
+
plot.fill[position.y] +
|
|
3604
|
+
' is ' +
|
|
3605
|
+
plot.plotData[position.x][position.y] +
|
|
3606
|
+
'</p>\n';
|
|
3624
3607
|
}
|
|
3608
|
+
verboseText = '<p>' + verboseText + '</p>\n';
|
|
3625
3609
|
}
|
|
3626
3610
|
|
|
3611
|
+
// set outout text
|
|
3612
|
+
if (constants.textMode == 'verbose') {
|
|
3613
|
+
output = verboseText;
|
|
3614
|
+
} else if (constants.textMode == 'terse') {
|
|
3615
|
+
output = terseText;
|
|
3616
|
+
}
|
|
3617
|
+
constants.verboseText = verboseText;
|
|
3618
|
+
|
|
3627
3619
|
if (constants.infoDiv) constants.infoDiv.innerHTML = output;
|
|
3628
3620
|
if (constants.review) {
|
|
3629
3621
|
if (output.length > 0) {
|
|
@@ -7571,6 +7563,9 @@ class Control {
|
|
|
7571
7563
|
// caption
|
|
7572
7564
|
display.displayInfo('caption', plot.caption);
|
|
7573
7565
|
pressedL = false;
|
|
7566
|
+
} else if (e.key == 'f') {
|
|
7567
|
+
display.displayInfo('fill', plot.fill);
|
|
7568
|
+
pressedL = false;
|
|
7574
7569
|
} else if (e.key != 'l') {
|
|
7575
7570
|
pressedL = false;
|
|
7576
7571
|
}
|