juxscript 1.1.192 → 1.1.193
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataframe.d.ts","sourceRoot":"","sources":["dataframe.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"dataframe.d.ts","sourceRoot":"","sources":["dataframe.ts"],"names":[],"mappings":"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"}
|
|
@@ -360,8 +360,8 @@ export class DataFrameComponent extends BaseComponent {
|
|
|
360
360
|
this._table.columns(columnDefs).rows(this._df.toRows());
|
|
361
361
|
}
|
|
362
362
|
const isMalformed = this._detectMalformedData(this._df);
|
|
363
|
-
if (isMalformed && this.
|
|
364
|
-
this._updateStatus(`${sourceName} — ${this._df.height} rows × ${this._df.width} cols (Data may
|
|
363
|
+
if (isMalformed && this._rawFileData) {
|
|
364
|
+
this._updateStatus(`${sourceName} — ${this._df.height} rows × ${this._df.width} cols (Data may need reformatting)`, 'warning');
|
|
365
365
|
requestAnimationFrame(() => {
|
|
366
366
|
const statusEl = document.getElementById(`${this._id}-status`);
|
|
367
367
|
if (statusEl) {
|
|
@@ -376,12 +376,13 @@ export class DataFrameComponent extends BaseComponent {
|
|
|
376
376
|
}
|
|
377
377
|
else {
|
|
378
378
|
this._updateStatus(`${sourceName} — ${this._df.height} rows × ${this._df.width} cols`, 'success');
|
|
379
|
-
if
|
|
379
|
+
// Always show settings button if we have raw file data
|
|
380
|
+
if (this._rawFileData) {
|
|
380
381
|
requestAnimationFrame(() => {
|
|
381
382
|
const statusEl = document.getElementById(`${this._id}-status`);
|
|
382
383
|
if (statusEl) {
|
|
383
384
|
const settingsBtn = document.createElement('button');
|
|
384
|
-
settingsBtn.textContent = 'Settings';
|
|
385
|
+
settingsBtn.textContent = 'Import Settings';
|
|
385
386
|
settingsBtn.className = 'jux-button jux-button-sm jux-button-ghost';
|
|
386
387
|
settingsBtn.style.marginLeft = '0.5rem';
|
|
387
388
|
settingsBtn.addEventListener('click', () => this._showReshapeModal());
|
|
@@ -485,10 +486,7 @@ export class DataFrameComponent extends BaseComponent {
|
|
|
485
486
|
max="50"
|
|
486
487
|
style="width: 100%;"
|
|
487
488
|
/>
|
|
488
|
-
<div class="jux-reshape-hint">
|
|
489
|
-
<strong>Detected issue:</strong> The current header row appears to contain metadata or empty values.
|
|
490
|
-
Row ${suggestedRow} looks like it contains the actual column headers.
|
|
491
|
-
Adjust the value above and check the preview below. The Row column shows the index for each row.
|
|
489
|
+
<div id="${this._id}-reshape-hint" class="jux-reshape-hint">
|
|
492
490
|
</div>
|
|
493
491
|
</div>
|
|
494
492
|
<div class="jux-reshape-preview-container">
|
|
@@ -526,7 +524,6 @@ export class DataFrameComponent extends BaseComponent {
|
|
|
526
524
|
this._renderMultiSheet(sheets, this._rawFileData.file.name);
|
|
527
525
|
}
|
|
528
526
|
else {
|
|
529
|
-
this._showReshapeWarning = false;
|
|
530
527
|
this._setDataFrame(sheets[sheetNames[0]], this._rawFileData.file.name);
|
|
531
528
|
}
|
|
532
529
|
this._reshapeModal.closeModal();
|
|
@@ -542,8 +539,16 @@ export class DataFrameComponent extends BaseComponent {
|
|
|
542
539
|
await new Promise(resolve => requestAnimationFrame(resolve));
|
|
543
540
|
const headerRowInput = document.getElementById(`${this._id}-header-row`);
|
|
544
541
|
const previewDiv = document.getElementById(`${this._id}-preview`);
|
|
542
|
+
const hintDiv = document.getElementById(`${this._id}-reshape-hint`);
|
|
543
|
+
const updateHint = (headerRow) => {
|
|
544
|
+
if (!hintDiv)
|
|
545
|
+
return;
|
|
546
|
+
hintDiv.innerHTML = `The data starting at <strong>row ${headerRow}</strong> will be used as column headers. ` +
|
|
547
|
+
`Rows before it will be skipped. The preview below shows the row index as the first column.`;
|
|
548
|
+
};
|
|
545
549
|
const updatePreview = async () => {
|
|
546
550
|
const headerRow = parseInt(headerRowInput?.value) || 0;
|
|
551
|
+
updateHint(headerRow);
|
|
547
552
|
try {
|
|
548
553
|
const sheets = await this._driver.streamFileMultiSheet(this._rawFileData.file, {
|
|
549
554
|
headerRow,
|
|
@@ -556,15 +561,17 @@ export class DataFrameComponent extends BaseComponent {
|
|
|
556
561
|
return;
|
|
557
562
|
}
|
|
558
563
|
const dataRows = firstSheet.toRows().slice(0, 10);
|
|
559
|
-
const
|
|
560
|
-
const
|
|
564
|
+
const idxWidth = 6;
|
|
565
|
+
const colWidth = 22;
|
|
566
|
+
const headerLine = 'Idx'.padEnd(idxWidth) + firstSheet.columns.map(c => String(c).substring(0, colWidth - 2).padEnd(colWidth)).join('| ');
|
|
567
|
+
const separator = '─'.repeat(Math.min(headerLine.length, 140));
|
|
561
568
|
const preview = dataRows.map((row, i) => {
|
|
562
|
-
const rowIdx = String(headerRow + 1 + i).padEnd(
|
|
563
|
-
const cols = Object.values(row).map(v => String(v ?? '').padEnd(
|
|
569
|
+
const rowIdx = String(headerRow + 1 + i).padEnd(idxWidth);
|
|
570
|
+
const cols = Object.values(row).map(v => String(v ?? '').substring(0, colWidth - 2).padEnd(colWidth)).join('| ');
|
|
564
571
|
return `${rowIdx}${cols}`;
|
|
565
572
|
}).join('\n');
|
|
566
573
|
if (previewDiv) {
|
|
567
|
-
previewDiv.textContent = `${
|
|
574
|
+
previewDiv.textContent = `${headerLine}\n${separator}\n${preview}`;
|
|
568
575
|
}
|
|
569
576
|
}
|
|
570
577
|
catch (err) {
|
|
@@ -605,7 +612,8 @@ export class DataFrameComponent extends BaseComponent {
|
|
|
605
612
|
<label style="display: block; font-weight: 600; margin-bottom: 0.5rem;">Skip Rows Before Header</label>
|
|
606
613
|
<input type="number" id="${this._id}-skip-rows" class="jux-input-element" value="0" min="0" max="50" style="width: 100%;" />
|
|
607
614
|
</div>
|
|
608
|
-
<div class="jux-reshape-
|
|
615
|
+
<div id="${this._id}-reshape-hint" class="jux-reshape-hint"></div>
|
|
616
|
+
<div class="jux-reshape-preview-container" style="margin-top: 1rem;">
|
|
609
617
|
<div style="font-weight: 600; margin-bottom: 0.5rem; color: hsl(var(--foreground));">Preview</div>
|
|
610
618
|
<div id="${this._id}-preview" class="jux-reshape-preview"></div>
|
|
611
619
|
</div>
|
|
@@ -640,7 +648,6 @@ export class DataFrameComponent extends BaseComponent {
|
|
|
640
648
|
hasHeader: true
|
|
641
649
|
});
|
|
642
650
|
await this._driver.store(this._rawFileData.file.name, df, { source: this._rawFileData.file.name });
|
|
643
|
-
this._showReshapeWarning = false;
|
|
644
651
|
this._setDataFrame(df, this._rawFileData.file.name);
|
|
645
652
|
this._reshapeModal.closeModal();
|
|
646
653
|
}
|
|
@@ -657,6 +664,7 @@ export class DataFrameComponent extends BaseComponent {
|
|
|
657
664
|
const headerRowInput = document.getElementById(`${this._id}-header-row`);
|
|
658
665
|
const skipRowsInput = document.getElementById(`${this._id}-skip-rows`);
|
|
659
666
|
const previewDiv = document.getElementById(`${this._id}-preview`);
|
|
667
|
+
const hintDiv = document.getElementById(`${this._id}-reshape-hint`);
|
|
660
668
|
if (this._rawFileData?.text) {
|
|
661
669
|
const detected = this._driver._detectDelimiter(this._rawFileData.text);
|
|
662
670
|
if (delimiterSelect)
|
|
@@ -665,12 +673,22 @@ export class DataFrameComponent extends BaseComponent {
|
|
|
665
673
|
if (headerRowInput)
|
|
666
674
|
headerRowInput.value = String(detectedHeaderRow);
|
|
667
675
|
}
|
|
676
|
+
const updateHint = () => {
|
|
677
|
+
if (!hintDiv)
|
|
678
|
+
return;
|
|
679
|
+
const headerRow = parseInt(headerRowInput?.value) || 0;
|
|
680
|
+
const skipRows = parseInt(skipRowsInput?.value) || 0;
|
|
681
|
+
hintDiv.innerHTML = `Using <strong>row ${headerRow}</strong> as column headers` +
|
|
682
|
+
(skipRows > 0 ? ` (skipping ${skipRows} rows before it)` : '') +
|
|
683
|
+
`. The Idx column shows the file row index.`;
|
|
684
|
+
};
|
|
668
685
|
const updatePreview = () => {
|
|
669
686
|
if (!this._rawFileData?.text)
|
|
670
687
|
return;
|
|
671
688
|
const delim = delimiterSelect?.value || ',';
|
|
672
689
|
const headerRow = parseInt(headerRowInput?.value) || 0;
|
|
673
690
|
const skipRows = parseInt(skipRowsInput?.value) || 0;
|
|
691
|
+
updateHint();
|
|
674
692
|
try {
|
|
675
693
|
const df = this._driver.parseCSV(this._rawFileData.text, {
|
|
676
694
|
delimiter: delim,
|
|
@@ -680,15 +698,17 @@ export class DataFrameComponent extends BaseComponent {
|
|
|
680
698
|
maxRows: 10
|
|
681
699
|
});
|
|
682
700
|
const dataRows = df.toRows();
|
|
683
|
-
const
|
|
684
|
-
const
|
|
701
|
+
const idxWidth = 6;
|
|
702
|
+
const colWidth = 22;
|
|
703
|
+
const headerLine = 'Idx'.padEnd(idxWidth) + df.columns.map(c => String(c).substring(0, colWidth - 2).padEnd(colWidth)).join('| ');
|
|
704
|
+
const separator = '─'.repeat(Math.min(headerLine.length, 140));
|
|
685
705
|
const preview = dataRows.map((row, i) => {
|
|
686
|
-
const rowIdx = String(headerRow + skipRows + 1 + i).padEnd(
|
|
687
|
-
const cols = Object.values(row).map(v => String(v ?? '').padEnd(
|
|
706
|
+
const rowIdx = String(headerRow + skipRows + 1 + i).padEnd(idxWidth);
|
|
707
|
+
const cols = Object.values(row).map(v => String(v ?? '').substring(0, colWidth - 2).padEnd(colWidth)).join('| ');
|
|
688
708
|
return `${rowIdx}${cols}`;
|
|
689
709
|
}).join('\n');
|
|
690
710
|
if (previewDiv) {
|
|
691
|
-
previewDiv.textContent = `${
|
|
711
|
+
previewDiv.textContent = `${headerLine}\n${separator}\n${preview}`;
|
|
692
712
|
}
|
|
693
713
|
}
|
|
694
714
|
catch (err) {
|
|
@@ -452,9 +452,9 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
|
|
|
452
452
|
|
|
453
453
|
const isMalformed = this._detectMalformedData(this._df!);
|
|
454
454
|
|
|
455
|
-
if (isMalformed && this.
|
|
455
|
+
if (isMalformed && this._rawFileData) {
|
|
456
456
|
this._updateStatus(
|
|
457
|
-
`${sourceName} — ${this._df!.height} rows × ${this._df!.width} cols (Data may
|
|
457
|
+
`${sourceName} — ${this._df!.height} rows × ${this._df!.width} cols (Data may need reformatting)`,
|
|
458
458
|
'warning'
|
|
459
459
|
);
|
|
460
460
|
|
|
@@ -475,12 +475,13 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
|
|
|
475
475
|
'success'
|
|
476
476
|
);
|
|
477
477
|
|
|
478
|
-
if
|
|
478
|
+
// Always show settings button if we have raw file data
|
|
479
|
+
if (this._rawFileData) {
|
|
479
480
|
requestAnimationFrame(() => {
|
|
480
481
|
const statusEl = document.getElementById(`${this._id}-status`);
|
|
481
482
|
if (statusEl) {
|
|
482
483
|
const settingsBtn = document.createElement('button');
|
|
483
|
-
settingsBtn.textContent = 'Settings';
|
|
484
|
+
settingsBtn.textContent = 'Import Settings';
|
|
484
485
|
settingsBtn.className = 'jux-button jux-button-sm jux-button-ghost';
|
|
485
486
|
settingsBtn.style.marginLeft = '0.5rem';
|
|
486
487
|
settingsBtn.addEventListener('click', () => this._showReshapeModal());
|
|
@@ -603,10 +604,7 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
|
|
|
603
604
|
max="50"
|
|
604
605
|
style="width: 100%;"
|
|
605
606
|
/>
|
|
606
|
-
<div class="jux-reshape-hint">
|
|
607
|
-
<strong>Detected issue:</strong> The current header row appears to contain metadata or empty values.
|
|
608
|
-
Row ${suggestedRow} looks like it contains the actual column headers.
|
|
609
|
-
Adjust the value above and check the preview below. The Row column shows the index for each row.
|
|
607
|
+
<div id="${this._id}-reshape-hint" class="jux-reshape-hint">
|
|
610
608
|
</div>
|
|
611
609
|
</div>
|
|
612
610
|
<div class="jux-reshape-preview-container">
|
|
@@ -648,7 +646,6 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
|
|
|
648
646
|
if (sheetNames.length > 1) {
|
|
649
647
|
this._renderMultiSheet(sheets, this._rawFileData!.file.name);
|
|
650
648
|
} else {
|
|
651
|
-
this._showReshapeWarning = false;
|
|
652
649
|
this._setDataFrame(sheets[sheetNames[0]], this._rawFileData!.file.name);
|
|
653
650
|
}
|
|
654
651
|
|
|
@@ -667,9 +664,19 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
|
|
|
667
664
|
|
|
668
665
|
const headerRowInput = document.getElementById(`${this._id}-header-row`) as HTMLInputElement;
|
|
669
666
|
const previewDiv = document.getElementById(`${this._id}-preview`)!;
|
|
667
|
+
const hintDiv = document.getElementById(`${this._id}-reshape-hint`)!;
|
|
668
|
+
|
|
669
|
+
const updateHint = (headerRow: number) => {
|
|
670
|
+
if (!hintDiv) return;
|
|
671
|
+
hintDiv.innerHTML = `The data starting at <strong>row ${headerRow}</strong> will be used as column headers. ` +
|
|
672
|
+
`Rows before it will be skipped. The preview below shows the row index as the first column.`;
|
|
673
|
+
};
|
|
670
674
|
|
|
671
675
|
const updatePreview = async () => {
|
|
672
676
|
const headerRow = parseInt(headerRowInput?.value) || 0;
|
|
677
|
+
|
|
678
|
+
updateHint(headerRow);
|
|
679
|
+
|
|
673
680
|
try {
|
|
674
681
|
const sheets = await this._driver.streamFileMultiSheet(this._rawFileData!.file, {
|
|
675
682
|
headerRow,
|
|
@@ -683,16 +690,20 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
|
|
|
683
690
|
}
|
|
684
691
|
|
|
685
692
|
const dataRows = firstSheet.toRows().slice(0, 10);
|
|
686
|
-
const
|
|
687
|
-
const
|
|
693
|
+
const idxWidth = 6;
|
|
694
|
+
const colWidth = 22;
|
|
695
|
+
|
|
696
|
+
const headerLine = 'Idx'.padEnd(idxWidth) + firstSheet.columns.map(c => String(c).substring(0, colWidth - 2).padEnd(colWidth)).join('| ');
|
|
697
|
+
const separator = '─'.repeat(Math.min(headerLine.length, 140));
|
|
698
|
+
|
|
688
699
|
const preview = dataRows.map((row, i) => {
|
|
689
|
-
const rowIdx = String(headerRow + 1 + i).padEnd(
|
|
690
|
-
const cols = Object.values(row).map(v => String(v ?? '').padEnd(
|
|
700
|
+
const rowIdx = String(headerRow + 1 + i).padEnd(idxWidth);
|
|
701
|
+
const cols = Object.values(row).map(v => String(v ?? '').substring(0, colWidth - 2).padEnd(colWidth)).join('| ');
|
|
691
702
|
return `${rowIdx}${cols}`;
|
|
692
703
|
}).join('\n');
|
|
693
704
|
|
|
694
705
|
if (previewDiv) {
|
|
695
|
-
previewDiv.textContent = `${
|
|
706
|
+
previewDiv.textContent = `${headerLine}\n${separator}\n${preview}`;
|
|
696
707
|
}
|
|
697
708
|
} catch (err: any) {
|
|
698
709
|
if (previewDiv) previewDiv.textContent = `Error: ${err.message}`;
|
|
@@ -735,7 +746,8 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
|
|
|
735
746
|
<label style="display: block; font-weight: 600; margin-bottom: 0.5rem;">Skip Rows Before Header</label>
|
|
736
747
|
<input type="number" id="${this._id}-skip-rows" class="jux-input-element" value="0" min="0" max="50" style="width: 100%;" />
|
|
737
748
|
</div>
|
|
738
|
-
<div class="jux-reshape-
|
|
749
|
+
<div id="${this._id}-reshape-hint" class="jux-reshape-hint"></div>
|
|
750
|
+
<div class="jux-reshape-preview-container" style="margin-top: 1rem;">
|
|
739
751
|
<div style="font-weight: 600; margin-bottom: 0.5rem; color: hsl(var(--foreground));">Preview</div>
|
|
740
752
|
<div id="${this._id}-preview" class="jux-reshape-preview"></div>
|
|
741
753
|
</div>
|
|
@@ -775,7 +787,6 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
|
|
|
775
787
|
});
|
|
776
788
|
|
|
777
789
|
await this._driver.store(this._rawFileData.file.name, df, { source: this._rawFileData.file.name });
|
|
778
|
-
this._showReshapeWarning = false;
|
|
779
790
|
this._setDataFrame(df, this._rawFileData.file.name);
|
|
780
791
|
|
|
781
792
|
this._reshapeModal!.closeModal();
|
|
@@ -794,6 +805,7 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
|
|
|
794
805
|
const headerRowInput = document.getElementById(`${this._id}-header-row`) as HTMLInputElement;
|
|
795
806
|
const skipRowsInput = document.getElementById(`${this._id}-skip-rows`) as HTMLInputElement;
|
|
796
807
|
const previewDiv = document.getElementById(`${this._id}-preview`)!;
|
|
808
|
+
const hintDiv = document.getElementById(`${this._id}-reshape-hint`)!;
|
|
797
809
|
|
|
798
810
|
if (this._rawFileData?.text) {
|
|
799
811
|
const detected = (this._driver as any)._detectDelimiter(this._rawFileData.text);
|
|
@@ -803,6 +815,15 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
|
|
|
803
815
|
if (headerRowInput) headerRowInput.value = String(detectedHeaderRow);
|
|
804
816
|
}
|
|
805
817
|
|
|
818
|
+
const updateHint = () => {
|
|
819
|
+
if (!hintDiv) return;
|
|
820
|
+
const headerRow = parseInt(headerRowInput?.value) || 0;
|
|
821
|
+
const skipRows = parseInt(skipRowsInput?.value) || 0;
|
|
822
|
+
hintDiv.innerHTML = `Using <strong>row ${headerRow}</strong> as column headers` +
|
|
823
|
+
(skipRows > 0 ? ` (skipping ${skipRows} rows before it)` : '') +
|
|
824
|
+
`. The Idx column shows the file row index.`;
|
|
825
|
+
};
|
|
826
|
+
|
|
806
827
|
const updatePreview = () => {
|
|
807
828
|
if (!this._rawFileData?.text) return;
|
|
808
829
|
|
|
@@ -810,6 +831,8 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
|
|
|
810
831
|
const headerRow = parseInt(headerRowInput?.value) || 0;
|
|
811
832
|
const skipRows = parseInt(skipRowsInput?.value) || 0;
|
|
812
833
|
|
|
834
|
+
updateHint();
|
|
835
|
+
|
|
813
836
|
try {
|
|
814
837
|
const df = this._driver.parseCSV(this._rawFileData.text, {
|
|
815
838
|
delimiter: delim,
|
|
@@ -820,16 +843,20 @@ export class DataFrameComponent extends BaseComponent<DataFrameState> {
|
|
|
820
843
|
});
|
|
821
844
|
|
|
822
845
|
const dataRows = df.toRows();
|
|
823
|
-
const
|
|
824
|
-
const
|
|
846
|
+
const idxWidth = 6;
|
|
847
|
+
const colWidth = 22;
|
|
848
|
+
|
|
849
|
+
const headerLine = 'Idx'.padEnd(idxWidth) + df.columns.map(c => String(c).substring(0, colWidth - 2).padEnd(colWidth)).join('| ');
|
|
850
|
+
const separator = '─'.repeat(Math.min(headerLine.length, 140));
|
|
851
|
+
|
|
825
852
|
const preview = dataRows.map((row, i) => {
|
|
826
|
-
const rowIdx = String(headerRow + skipRows + 1 + i).padEnd(
|
|
827
|
-
const cols = Object.values(row).map(v => String(v ?? '').padEnd(
|
|
853
|
+
const rowIdx = String(headerRow + skipRows + 1 + i).padEnd(idxWidth);
|
|
854
|
+
const cols = Object.values(row).map(v => String(v ?? '').substring(0, colWidth - 2).padEnd(colWidth)).join('| ');
|
|
828
855
|
return `${rowIdx}${cols}`;
|
|
829
856
|
}).join('\n');
|
|
830
857
|
|
|
831
858
|
if (previewDiv) {
|
|
832
|
-
previewDiv.textContent = `${
|
|
859
|
+
previewDiv.textContent = `${headerLine}\n${separator}\n${preview}`;
|
|
833
860
|
}
|
|
834
861
|
} catch (err: any) {
|
|
835
862
|
if (previewDiv) previewDiv.textContent = `Error: ${err.message}`;
|